| ; 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} |
| ;. |