If a lifetime.end marker occurs along one path through the extraction region, but not another, then it's still incorrect to lift the marker, because there is some path through the extracted function which would ordinarily not reach the marker. If the call to the extracted function is in a loop, unrolling can cause inputs to the function to become optimized out as undef after the first iteration. To prevent incorrect stack slot merging in the calling function, it should be sufficient to lift lifetime.start markers for region inputs. I've tested this theory out by doing a stage2 check-all with randomized splitting enabled. This is a follow-up to r353973, and there's additional context for this change in https://reviews.llvm.org/D57834. rdar://47896986 Differential Revision: https://reviews.llvm.org/D58253 llvm-svn: 354159
71 lines
2.1 KiB
LLVM
71 lines
2.1 KiB
LLVM
; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
|
|
; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
|
|
|
|
%"class.base" = type { %"struct.base"* }
|
|
%"struct.base" = type opaque
|
|
|
|
@g = external local_unnamed_addr global i32, align 4
|
|
|
|
; CHECK-LABEL: define{{.*}}@caller(
|
|
; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %tmp.i)
|
|
; CHECK-NEXT: call void @callee_unknown_use1.{{.*}}(i8* %tmp.i
|
|
|
|
define i32 @callee_unknown_use1(i32 %arg) local_unnamed_addr #0 {
|
|
; CHECK-LABEL:define{{.*}}@callee_unknown_use1.{{[0-9]}}
|
|
; CHECK-NOT: alloca
|
|
bb:
|
|
%tmp = alloca i8, align 4
|
|
%tmp2 = load i32, i32* @g, align 4, !tbaa !2
|
|
%tmp3 = add nsw i32 %tmp2, 1
|
|
%tmp4 = icmp slt i32 %arg, 0
|
|
br i1 %tmp4, label %bb6, label %bb5
|
|
|
|
bb5: ; preds = %bb
|
|
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp) #2
|
|
store i32 %tmp3, i32* @g, align 4, !tbaa !2
|
|
%tmp11 = bitcast i8* %tmp to i32*
|
|
call void @bar(i32* nonnull %tmp11) #2
|
|
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp) #2
|
|
br label %bb6
|
|
|
|
bb6: ; preds = %bb5, %bb
|
|
%tmp7 = phi i32 [ 1, %bb5 ], [ 0, %bb ]
|
|
%tmp1 = bitcast i8* %tmp to i32*
|
|
ret i32 %tmp7
|
|
}
|
|
|
|
|
|
; Function Attrs: argmemonly nounwind
|
|
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
|
|
|
|
declare void @bar(i32*) local_unnamed_addr #2
|
|
declare void @bar2(i32*, i32*) local_unnamed_addr #1
|
|
|
|
|
|
; Function Attrs: argmemonly nounwind
|
|
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
define i32 @caller(i32 %arg) local_unnamed_addr #0 {
|
|
bb:
|
|
%tmp = tail call i32 @callee_unknown_use1(i32 %arg)
|
|
ret i32 %tmp
|
|
}
|
|
|
|
attributes #0 = { nounwind uwtable}
|
|
attributes #1 = { argmemonly nounwind }
|
|
attributes #2 = { nounwind }
|
|
|
|
!llvm.module.flags = !{!0}
|
|
!llvm.ident = !{!1}
|
|
|
|
!0 = !{i32 1, !"wchar_size", i32 4}
|
|
!1 = !{!"clang version 5.0.0 (trunk 303574)"}
|
|
!2 = !{!3, !3, i64 0}
|
|
!3 = !{!"int", !4, i64 0}
|
|
!4 = !{!"omnipotent char", !5, i64 0}
|
|
!5 = !{!"Simple C/C++ TBAA"}
|
|
|
|
|
|
|