blob: 6e543b8c87fc7042615332c9b62583d6f45737a3 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
; RUN: opt < %s -passes='require<profile-summary>,chr' -S | FileCheck %s
declare void @foo()
declare void @bar()
declare void @baz(i64)
; Test that when we have a static alloca in an entry block that will get split,
; the alloca remains static and we preserve its lifetime annotations.
define void @test_chr_with_lifetimes(ptr %i) !prof !14 {
; CHECK-LABEL: @test_chr_with_lifetimes(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TEST:%.*]] = alloca i32, align 8
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[TMP0]], 0
; CHECK-NEXT: [[TMP9:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP8:%.*]] = select i1 true, i1 [[TMP9]], i1 false, !prof [[PROF15:![0-9]+]]
; CHECK-NEXT: [[TMP11:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP8]], i1 [[TMP11]], i1 false, !prof [[PROF15]]
; CHECK-NEXT: br i1 [[TMP5]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF16:![0-9]+]]
; CHECK: entry.split:
; CHECK-NEXT: [[TMP6:%.*]] = select i1 true, i64 0, i64 4, !prof [[PROF17:![0-9]+]]
; CHECK-NEXT: call void @baz(i64 [[TMP6]])
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF18:![0-9]+]]
; CHECK: bb0:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BB1]]
; CHECK: entry.split.nonchr:
; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP1]], i64 0, i64 4, !prof [[PROF17]]
; CHECK-NEXT: call void @baz(i64 [[TMP7]])
; CHECK-NEXT: br i1 [[TMP1]], label [[BB0_NONCHR:%.*]], label [[BB1]], !prof [[PROF17]]
; CHECK: bb0.nonchr:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BB1]]
; CHECK: bb1:
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TEST]])
; CHECK-NEXT: store ptr [[TEST]], ptr [[I]], align 8
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[TMP2:%.*]] = phi ptr [ [[TMP3:%.*]], [[BB2]] ], [ null, [[BB1]] ]
; CHECK-NEXT: [[TMP3]] = getelementptr i8, ptr [[TMP2]], i64 24
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq ptr [[TMP2]], [[I]]
; CHECK-NEXT: br i1 [[TMP4]], label [[BB3:%.*]], label [[BB2]]
; CHECK: bb3:
; CHECK-NEXT: ret void
;
entry:
%1 = load i32, ptr %i
%2 = icmp eq i32 %1, 0
%3 = select i1 %2, i64 4, i64 0, !prof !15
%test = alloca i32, align 8
call void @baz(i64 %3)
br i1 %2, label %bb1, label %bb0, !prof !15
bb0:
call void @foo()
br label %bb1
bb1:
call void @llvm.lifetime.start.p0(ptr %test)
store ptr %test, ptr %i, align 8
br label %bb2
bb2:
%4 = phi ptr [ %5, %bb2 ], [ null, %bb1 ]
%5 = getelementptr i8, ptr %4, i64 24
%6 = icmp eq ptr %4, %i
br i1 %6, label %bb3, label %bb2
bb3:
ret void
}
; Test that we remove lifetime markers that would otherwise refer to phi
; nodes given the dynamic allocas they referred to have been duplicated.
define void @test_chr_dynamic_alloca(ptr %i) !prof !14 {
; CHECK-LABEL: @test_chr_dynamic_alloca(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[I:%.*]], align 4
; CHECK-NEXT: [[TEST2:%.*]] = icmp eq i32 [[TEST1]], 5
; CHECK-NEXT: br i1 [[TEST2]], label [[BB4:%.*]], label [[BB3:%.*]]
; CHECK: bb4:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[TMP0]], 0
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = select i1 true, i1 [[TMP2]], i1 false, !prof [[PROF15]]
; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i1 [[TMP4]], i1 false, !prof [[PROF15]]
; CHECK-NEXT: br i1 [[TMP5]], label [[BB4_SPLIT:%.*]], label [[BB4_SPLIT_NONCHR:%.*]], !prof [[PROF16]]
; CHECK: bb4.split:
; CHECK-NEXT: [[TMP6:%.*]] = select i1 true, i64 0, i64 4, !prof [[PROF17]]
; CHECK-NEXT: [[TEST:%.*]] = alloca i32, align 8
; CHECK-NEXT: call void @baz(i64 [[TMP6]])
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF18]]
; CHECK: bb0:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: store ptr [[TEST]], ptr [[I]], align 8
; CHECK-NEXT: br label [[BB1]]
; CHECK: bb4.split.nonchr:
; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP1]], i64 0, i64 4, !prof [[PROF17]]
; CHECK-NEXT: [[TEST_NONCHR:%.*]] = alloca i32, align 8
; CHECK-NEXT: call void @baz(i64 [[TMP7]])
; CHECK-NEXT: br i1 [[TMP1]], label [[BB0_NONCHR:%.*]], label [[BB1]], !prof [[PROF17]]
; CHECK: bb0.nonchr:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: store ptr [[TEST_NONCHR]], ptr [[I]], align 8
; CHECK-NEXT: br label [[BB1]]
; CHECK: bb1:
; CHECK-NEXT: [[TMP8:%.*]] = phi ptr [ [[TEST]], [[BB0]] ], [ [[TEST]], [[BB4_SPLIT]] ], [ [[TEST_NONCHR]], [[BB0_NONCHR]] ], [ [[TEST_NONCHR]], [[BB4_SPLIT_NONCHR]] ]
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: store ptr [[TMP8]], ptr [[I]], align 8
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[TMP9:%.*]] = phi ptr [ [[TMP10:%.*]], [[BB2]] ], [ null, [[BB1]] ]
; CHECK-NEXT: [[TMP10]] = getelementptr i8, ptr [[TMP9]], i64 24
; CHECK-NEXT: [[TEST5:%.*]] = load ptr, ptr [[TMP8]], align 8
; CHECK-NEXT: [[TMP11:%.*]] = icmp eq ptr [[TMP9]], [[TEST5]]
; CHECK-NEXT: br i1 [[TMP11]], label [[BB3]], label [[BB2]]
; CHECK: bb3:
; CHECK-NEXT: ret void
;
entry:
%test1 = load i32, ptr %i
%test2 = icmp eq i32 %test1, 5
br i1 %test2, label %bb4, label %bb3
bb4:
%1 = load i32, ptr %i
%2 = icmp eq i32 %1, 0
%3 = select i1 %2, i64 4, i64 0, !prof !15
%test = alloca i32, align 8
call void @baz(i64 %3)
br i1 %2, label %bb1, label %bb0, !prof !15
bb0:
call void @foo()
call void @llvm.lifetime.start.p0(ptr %test)
store ptr %test, ptr %i, align 8
br label %bb1
bb1:
call void @bar()
call void @llvm.lifetime.start.p0(ptr %test)
store ptr %test, ptr %i, align 8
br label %bb2
bb2:
%4 = phi ptr [ %5, %bb2 ], [ null, %bb1 ]
%5 = getelementptr i8, ptr %4, i64 24
%test5 = load ptr, ptr %test
call void @llvm.lifetime.end.p0(ptr %test)
%6 = icmp eq ptr %4, %test5
br i1 %6, label %bb3, label %bb2
bb3:
ret void
}
; Test that we do not move around allocas that occur in the entry block
; before splitting. If we accidentally sink them, we can move them after
; their users.
define void @test_no_move_allocas(ptr %i) !prof !14 {
; CHECK-LABEL: @test_no_move_allocas(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TEST:%.*]] = alloca i32, align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TEST]])
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I:%.*]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[TMP0]], 0
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = select i1 true, i1 [[TMP2]], i1 false, !prof [[PROF15]]
; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i1 [[TMP4]], i1 false, !prof [[PROF15]]
; CHECK-NEXT: br i1 [[TMP5]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF16]]
; CHECK: entry.split:
; CHECK-NEXT: [[TMP6:%.*]] = select i1 true, i64 0, i64 4, !prof [[PROF17]]
; CHECK-NEXT: call void @baz(i64 [[TMP6]])
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB0:%.*]], !prof [[PROF18]]
; CHECK: bb0:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BB1]]
; CHECK: entry.split.nonchr:
; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP1]], i64 0, i64 4, !prof [[PROF17]]
; CHECK-NEXT: call void @baz(i64 [[TMP7]])
; CHECK-NEXT: br i1 [[TMP1]], label [[BB0_NONCHR:%.*]], label [[BB1]], !prof [[PROF17]]
; CHECK: bb0.nonchr:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BB1]]
; CHECK: bb1:
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[TMP8:%.*]] = phi ptr [ [[TMP9:%.*]], [[BB2]] ], [ null, [[BB1]] ]
; CHECK-NEXT: [[TMP9]] = getelementptr i8, ptr [[TMP8]], i64 24
; CHECK-NEXT: [[TMP10:%.*]] = icmp eq ptr [[TMP8]], [[I]]
; CHECK-NEXT: br i1 [[TMP10]], label [[BB3:%.*]], label [[BB2]]
; CHECK: bb3:
; CHECK-NEXT: ret void
;
entry:
%test = alloca i32, align 8
call void @llvm.lifetime.start.p0(ptr %test)
%1 = load i32, ptr %i
%2 = icmp eq i32 %1, 0
%3 = select i1 %2, i64 4, i64 0, !prof !15
call void @baz(i64 %3)
br i1 %2, label %bb1, label %bb0, !prof !15
bb0:
call void @foo()
br label %bb1
bb1:
call void @bar()
br label %bb2
bb2:
%4 = phi ptr [ %5, %bb2 ], [ null, %bb1 ]
%5 = getelementptr i8, ptr %4, i64 24
%6 = icmp eq ptr %4, %i
br i1 %6, label %bb3, label %bb2
bb3:
ret void
}
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"ProfileSummary", !1}
!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
!2 = !{!"ProfileFormat", !"InstrProf"}
!3 = !{!"TotalCount", i64 10000}
!4 = !{!"MaxCount", i64 10}
!5 = !{!"MaxInternalCount", i64 1}
!6 = !{!"MaxFunctionCount", i64 1000}
!7 = !{!"NumCounts", i64 3}
!8 = !{!"NumFunctions", i64 3}
!9 = !{!"DetailedSummary", !10}
!10 = !{!11, !12, !13}
!11 = !{i32 10000, i64 100, i32 1}
!12 = !{i32 999000, i64 100, i32 1}
!13 = !{i32 999999, i64 1, i32 2}
!14 = !{!"function_entry_count", i64 100}
!15 = !{!"branch_weights", i32 0, i32 1}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
;.
; CHECK: [[META0:![0-9]+]] = !{i32 1, !"ProfileSummary", [[META1:![0-9]+]]}
; CHECK: [[META1]] = !{[[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]], [[META6:![0-9]+]], [[META7:![0-9]+]], [[META8:![0-9]+]], [[META9:![0-9]+]]}
; CHECK: [[META2]] = !{!"ProfileFormat", !"InstrProf"}
; CHECK: [[META3]] = !{!"TotalCount", i64 10000}
; CHECK: [[META4]] = !{!"MaxCount", i64 10}
; CHECK: [[META5]] = !{!"MaxInternalCount", i64 1}
; CHECK: [[META6]] = !{!"MaxFunctionCount", i64 1000}
; CHECK: [[META7]] = !{!"NumCounts", i64 3}
; CHECK: [[META8]] = !{!"NumFunctions", i64 3}
; CHECK: [[META9]] = !{!"DetailedSummary", [[META10:![0-9]+]]}
; CHECK: [[META10]] = !{[[META11:![0-9]+]], [[META12:![0-9]+]], [[META13:![0-9]+]]}
; CHECK: [[META11]] = !{i32 10000, i64 100, i32 1}
; CHECK: [[META12]] = !{i32 999000, i64 100, i32 1}
; CHECK: [[META13]] = !{i32 999999, i64 1, i32 2}
; CHECK: [[META14:![0-9]+]] = !{!"function_entry_count", i64 100}
; CHECK: [[PROF15]] = !{!"unknown", !"chr"}
; CHECK: [[PROF16]] = !{!"branch_weights", i32 1000, i32 0}
; CHECK: [[PROF17]] = !{!"branch_weights", i32 1, i32 0}
; CHECK: [[PROF18]] = !{!"branch_weights", i32 0, i32 1}
;.