Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -999,14 +999,34 @@ const DataLayout &MDL = Preheader->getModule()->getDataLayout(); + // Do we know this object does not escape ? + bool IsKnownNonEscapingObject = false; if (SafetyInfo->MayThrow) { // If a loop can throw, we have to insert a store along each unwind edge. // That said, we can't actually make the unwind edge explicit. Therefore, // we have to prove that the store is dead along the unwind edge. // - // Currently, this code just special-cases alloca instructions. - if (!isa(GetUnderlyingObject(SomePtr, MDL))) - return false; + // If the underlying object is not an alloca, nor a pointer that does not + // escape, then we can not effectively prove that the store is dead along + // the unwind edge. i.e. the caller of this function could have ways to + // access the pointed object. + Value *Object = GetUnderlyingObject(SomePtr, MDL); + // If this is a base pointer we do not understand, simply bail. + // We only handle alloca and return value from alloc-like fn right now. + if (!isa(Object)) { + if (!isAllocLikeFn(Object, TLI)) + return false; + // If this is an alloc like fn. There are more constraints we need to verify. + // More specifically, we must make sure that the pointer can not escape. + // + // NOTE: PointerMayBeCaptured is not enough as the pointer may have escaped + // even though its not captured by the enclosing function. Standard allocation + // functions like malloc, calloc, and operator new return values which can + // be assumed not to have previously escaped. + if (PointerMayBeCaptured(Object, true, true)) + return false; + IsKnownNonEscapingObject = true; + } } // Check that all of the pointers in the alias set have the same type. We @@ -1109,10 +1129,15 @@ // stores along paths which originally didn't have them without violating the // memory model. if (!SafeToInsertStore) { - Value *Object = GetUnderlyingObject(SomePtr, MDL); - SafeToInsertStore = - (isAllocLikeFn(Object, TLI) || isa(Object)) && + // If this is a known non-escaping object, it is safe to insert the stores. + if (IsKnownNonEscapingObject) + SafeToInsertStore = true; + else { + Value *Object = GetUnderlyingObject(SomePtr, MDL); + SafeToInsertStore = + (isAllocLikeFn(Object, TLI) || isa(Object)) && !PointerMayBeCaptured(Object, true, true); + } } // If we've still failed to prove we can sink the store, give up. Index: test/Transforms/LICM/scalar-promote-unwind.ll =================================================================== --- test/Transforms/LICM/scalar-promote-unwind.ll +++ test/Transforms/LICM/scalar-promote-unwind.ll @@ -137,14 +137,129 @@ resume { i8*, i32 } %lpad.val3 } -declare void @boo() -declare i32 @__gxx_personality_v0(...) +; The malloc'ed memory is not capture and therefore promoted. +define void @malloc_no_capture() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %call = call i8* @malloc(i64 4) + %0 = bitcast i8* %call to i32* + br label %for.body -declare i32 @llvm.eh.typeid.for(i8*) +; CHECK: for.body: +; CHECK-NOT: load +; CHECK-NOT: store +; CHECK: br +for.body: + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.latch ] + %1 = load i32, i32* %0, align 4 + %add = add nsw i32 %1, 1 + store i32 %add, i32* %0, align 4 + br label %for.call + +for.call: + invoke void @boo() + to label %invoke.cont unwind label %lpad + +invoke.cont: + br label %for.latch + +for.latch: + %inc = add i32 %i.0, 1 + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.end: + br label %fun.ret + +lpad: + %2 = landingpad { i8*, i32 } + catch i8* null + %3 = extractvalue { i8*, i32 } %2, 0 + %4 = extractvalue { i8*, i32 } %2, 1 + br label %catch + +catch: + %5 = call i8* @__cxa_begin_catch(i8* %3) #4 + %6 = bitcast i32* %0 to i8* + call void @free(i8* %6) + call void @__cxa_end_catch() + br label %fun.ret + +fun.ret: + ret void +} + +; The malloc'ed memory can be captured and therefore not promoted. +define void @malloc_capture(i32** noalias %A) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %call = call i8* @malloc(i64 4) + %0 = bitcast i8* %call to i32* + br label %for.body + +; CHECK: for.body: +; CHECK: load +; CHECK: store +; CHECK: br +for.body: + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.latch ] + %1 = load i32, i32* %0, align 4 + %add = add nsw i32 %1, 1 + store i32 %add, i32* %0, align 4 + br label %for.call + +for.call: + invoke void @boo_readnone() + to label %invoke.cont unwind label %lpad + +invoke.cont: + br label %for.latch + +for.latch: + store i32* %0, i32** %A + %inc = add i32 %i.0, 1 + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.end: + br label %fun.ret + +lpad: + %2 = landingpad { i8*, i32 } + catch i8* null + %3 = extractvalue { i8*, i32 } %2, 0 + %4 = extractvalue { i8*, i32 } %2, 1 + br label %catch + +catch: + %5 = call i8* @__cxa_begin_catch(i8* %3) #4 + %6 = bitcast i32* %0 to i8* + call void @free(i8* %6) + call void @__cxa_end_catch() + br label %fun.ret + +fun.ret: + ret void +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) + +; Function Attrs: nounwind +declare void @free(i8* nocapture) + +declare void @boo() + +; This is an artifical example, readnone functions by definition cannot unwind +; exceptions by calling the C++ exception throwing methods +; This function should only be used to test malloc_capture. +declare void @boo_readnone() readnone + +declare i32 @__gxx_personality_v0(...) declare i8* @__cxa_begin_catch(i8*) declare void @__cxa_end_catch() +declare i32 @llvm.eh.typeid.for(i8*) + declare void @f() uwtable