; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -split-machine-functions | FileCheck %s -check-prefix=MFS-DEFAULTS ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -split-machine-functions -mfs-psi-cutoff=0 -mfs-count-threshold=2000 | FileCheck %s --dump-input=always -check-prefix=MFS-OPTS1 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -split-machine-functions -mfs-psi-cutoff=950000 | FileCheck %s -check-prefix=MFS-OPTS2 define void @foo1(i1 zeroext %0) nounwind !prof !14 !section_prefix !15 { ;; Check that cold block is moved to .text.split. ; MFS-DEFAULTS-LABEL: foo1 ; MFS-DEFAULTS: .section .text.split.foo1 ; MFS-DEFAULTS-NEXT: foo1.cold: ; MFS-DEFAULTS-NOT: callq bar ; MFS-DEFAULTS-NEXT: callq baz br i1 %0, label %2, label %4, !prof !17 2: ; preds = %1 %3 = call i32 @bar() br label %6 4: ; preds = %1 %5 = call i32 @baz() br label %6 6: ; preds = %4, %2 %7 = tail call i32 @qux() ret void } define void @foo2(i1 zeroext %0) nounwind !prof !23 !section_prefix !16 { ;; Check that function marked unlikely is not split. ; MFS-DEFAULTS-LABEL: foo2 ; MFS-DEFAULTS-NOT: foo2.cold: br i1 %0, label %2, label %4, !prof !17 2: ; preds = %1 %3 = call i32 @bar() br label %6 4: ; preds = %1 %5 = call i32 @baz() br label %6 6: ; preds = %4, %2 %7 = tail call i32 @qux() ret void } define void @foo3(i1 zeroext %0) nounwind !section_prefix !15 { ;; Check that function without profile data is not split. ; MFS-DEFAULTS-LABEL: foo3 ; MFS-DEFAULTS-NOT: foo3.cold: br i1 %0, label %2, label %4 2: ; preds = %1 %3 = call i32 @bar() br label %6 4: ; preds = %1 %5 = call i32 @baz() br label %6 6: ; preds = %4, %2 %7 = tail call i32 @qux() ret void } define void @foo4(i1 zeroext %0, i1 zeroext %1) nounwind !prof !20 { ;; Check that count threshold works. ; MFS-OPTS1-LABEL: foo4 ; MFS-OPTS1: .section .text.split.foo4 ; MFS-OPTS1-NEXT: foo4.cold: ; MFS-OPTS1-NOT: callq bar ; MFS-OPTS1-NOT: callq baz ; MFS-OPTS1-NEXT: callq bam br i1 %0, label %3, label %7, !prof !18 3: %4 = call i32 @bar() br label %7 5: %6 = call i32 @baz() br label %7 7: br i1 %1, label %8, label %10, !prof !19 8: %9 = call i32 @bam() br label %12 10: %11 = call i32 @baz() br label %12 12: %13 = tail call i32 @qux() ret void } define void @foo5(i1 zeroext %0, i1 zeroext %1) nounwind !prof !20 { ;; Check that profile summary info cutoff works. ; MFS-OPTS2-LABEL: foo5 ; MFS-OPTS2: .section .text.split.foo5 ; MFS-OPTS2-NEXT: foo5.cold: ; MFS-OPTS2-NOT: callq bar ; MFS-OPTS2-NOT: callq baz ; MFS-OPTS2-NEXT: callq bam br i1 %0, label %3, label %7, !prof !21 3: %4 = call i32 @bar() br label %7 5: %6 = call i32 @baz() br label %7 7: br i1 %1, label %8, label %10, !prof !22 8: %9 = call i32 @bam() br label %12 10: %11 = call i32 @baz() br label %12 12: %13 = call i32 @qux() ret void } define void @foo6(i1 zeroext %0) nounwind section "nosplit" !prof !14 { ;; Check that function with section attribute is not split. ; MFS-DEFAULTS-LABEL: foo6 ; MFS-DEFAULTS-NOT: foo6.cold: br i1 %0, label %2, label %4, !prof !17 2: ; preds = %1 %3 = call i32 @bar() br label %6 4: ; preds = %1 %5 = call i32 @baz() br label %6 6: ; preds = %4, %2 %7 = tail call i32 @qux() ret void } define i32 @foo7(i1 zeroext %0) personality ptr @__gxx_personality_v0 !prof !14 { ;; Check that a single cold ehpad is split out. ; MFS-DEFAULTS-LABEL: foo7 ; MFS-DEFAULTS: .section .text.split.foo7,"ax",@progbits ; MFS-DEFAULTS-NEXT: foo7.cold: ; MFS-DEFAULTS: callq baz ; MFS-DEFAULTS: callq _Unwind_Resume@PLT entry: invoke void @_Z1fv() to label %try.cont unwind label %lpad lpad: %1 = landingpad { ptr, i32 } cleanup catch ptr @_ZTIi resume { ptr, i32 } %1 try.cont: br i1 %0, label %2, label %4, !prof !17 2: ; preds = try.cont %3 = call i32 @bar() br label %6 4: ; preds = %1 %5 = call i32 @baz() br label %6 6: ; preds = %4, %2 %7 = tail call i32 @qux() ret i32 %7 } define i32 @foo8(i1 zeroext %0) personality ptr @__gxx_personality_v0 !prof !14 { ;; Check that all ehpads are treated as hot if one of them is hot. ; MFS-DEFAULTS-LABEL: foo8 ; MFS-DEFAULTS: callq _Unwind_Resume@PLT ; MFS-DEFAULTS: callq _Unwind_Resume@PLT ; MFS-DEFAULTS: .section .text.split.foo8,"ax",@progbits ; MFS-DEFAULTS-NEXT: foo8.cold: ; MFS-DEFAULTS: callq baz entry: invoke void @_Z1fv() to label %try.cont unwind label %lpad1 lpad1: %1 = landingpad { ptr, i32 } cleanup catch ptr @_ZTIi resume { ptr, i32 } %1 try.cont: br i1 %0, label %hot, label %cold, !prof !17 hot: %2 = call i32 @bar() invoke void @_Z1fv() to label %exit unwind label %lpad2, !prof !21 lpad2: %3 = landingpad { ptr, i32 } cleanup catch ptr @_ZTIi resume { ptr, i32 } %3 cold: %4 = call i32 @baz() br label %exit exit: %5 = tail call i32 @qux() ret i32 %5 } define void @foo9(i1 zeroext %0) nounwind #0 !prof !14 { ;; Check that function with section attribute is not split. ; MFS-DEFAULTS-LABEL: foo9 ; MFS-DEFAULTS-NOT: foo9.cold: br i1 %0, label %2, label %4, !prof !17 2: ; preds = %1 %3 = call i32 @bar() br label %6 4: ; preds = %1 %5 = call i32 @baz() br label %6 6: ; preds = %4, %2 %7 = tail call i32 @qux() ret void } define i32 @foo10(i1 zeroext %0) personality ptr @__gxx_personality_v0 !prof !14 { ;; Check that nop is inserted just before the EH pad if it's beginning a section. ; MFS-DEFAULTS-LABEL: foo10 ; MFS-DEFAULTS-LABEL: callq baz ; MFS-DEFAULTS: .section .text.split.foo10,"ax",@progbits ; MFS-DEFAULTS-NEXT: foo10.cold: ; MFS-DEFAULTS: nop ; MFS-DEFAULTS: callq _Unwind_Resume@PLT entry: invoke void @_Z1fv() to label %try.cont unwind label %lpad, !prof !17 lpad: %1 = landingpad { ptr, i32 } cleanup catch ptr @_ZTIi resume { ptr, i32 } %1 try.cont: %2 = call i32 @baz() ret i32 %2 } declare i32 @bar() declare i32 @baz() declare i32 @bam() declare i32 @qux() declare void @_Z1fv() declare i32 @__gxx_personality_v0(...) @_ZTIi = external constant ptr attributes #0 = { "implicit-section-name"="nosplit" } !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 5} !9 = !{!"DetailedSummary", !10} !10 = !{!11, !12, !13} !11 = !{i32 10000, i64 100, i32 1} !12 = !{i32 999900, i64 100, i32 1} !13 = !{i32 999999, i64 1, i32 2} !14 = !{!"function_entry_count", i64 7000} !15 = !{!"function_section_prefix", !"hot"} !16 = !{!"function_section_prefix", !"unlikely"} !17 = !{!"branch_weights", i32 7000, i32 0} !18 = !{!"branch_weights", i32 3000, i32 4000} !19 = !{!"branch_weights", i32 1000, i32 6000} !20 = !{!"function_entry_count", i64 10000} !21 = !{!"branch_weights", i32 6000, i32 4000} !22 = !{!"branch_weights", i32 80, i32 9920} !23 = !{!"function_entry_count", i64 7}