diff --git a/llvm/test/DebugInfo/X86/machine-function-splitter.ll b/llvm/test/DebugInfo/X86/machine-function-splitter.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/machine-function-splitter.ll @@ -0,0 +1,210 @@ +;; Basic block sections used by MFS is only supported on x86, elf based systems. +; UNSUPPORTED: system-windows, system-darwin +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-machine-functions -filetype=obj %s -o %t +; RUN: llvm-objdump -l %t | FileCheck %s + +;; Check line numbers in the hot part +; CHECK: 0000000000000000 : +; CHECK-NEXT: ; foo(): +; CHECK-NEXT: ; /home/llvm-dev/working/llvm-project/build/split_functions.c:3 +; CHECK-NEXT: 0: 89 f8 movl %edi, %eax +; CHECK-NEXT: ; /home/llvm-dev/working/llvm-project/build/split_functions.c:4 +; CHECK-NEXT: 2: 69 cf 29 5c 8f c2 imull $3264175145, %edi, %ecx +; CHECK: ; /home/llvm-dev/working/llvm-project/build/split_functions.c:5 +; CHECK-NEXT: 1d: 83 c0 01 addl $1, %eax +; CHECK: ; /home/llvm-dev/working/llvm-project/build/split_functions.c:9 +; CHECK-NEXT: 20: c3 retq + +;; Check line numbers in the cold part +; CHECK: 0000000000000000 : +; CHECK-NEXT: ; foo(): +; CHECK-NEXT: ; /home/llvm-dev/working/llvm-project/build/split_functions.c:7 +; CHECK-NEXT: 0: 01 c0 addl %eax, %eax +; CHECK: ; /home/llvm-dev/working/llvm-project/build/split_functions.c:9 +; CHECK-NEXT: 20: c3 retq + +;; Generated from the following source and commands: +;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +;; __attribute__((noinline)) int foo(int i) { +;; if (i % 100) { +;; return i + 1; +;; } else { +;; return i * 10 % 3; +;; } +;; } +;; +;; +;; int main(int argc, char *argv[]) { +;; int total = 0; +;; for (int i = 0; i < 1000; ++i) { +;; total += foo(i); +;; } +;; printf("%d\n", total); +;; } +;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +;; clang -fprofile-generate -O2 split_functions.c +;; ./a.out > /dev/null +;; llvm-profdata merge -o default.profdata default_*.profraw +;; clang -fprofile-use -O2 -g -S -emit-llvm split_functions.c +;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +; ModuleID = 'split_functions.c' +source_filename = "split_functions.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 + +; Function Attrs: inlinehint noinline norecurse nounwind readnone uwtable +define dso_local i32 @foo(i32 %i) local_unnamed_addr #0 !dbg !40 !prof !46 { +entry: + call void @llvm.dbg.value(metadata i32 %i, metadata !45, metadata !DIExpression()), !dbg !47 + %rem = srem i32 %i, 100, !dbg !48 + %tobool.not = icmp eq i32 %rem, 0, !dbg !48 + br i1 %tobool.not, label %if.else, label %if.then, !dbg !50, !prof !51 + +if.then: ; preds = %entry + %add = add nsw i32 %i, 1, !dbg !52 + br label %return, !dbg !54 + +if.else: ; preds = %entry + %mul = mul nsw i32 %i, 10, !dbg !55 + %rem1 = srem i32 %mul, 3, !dbg !57 + br label %return, !dbg !58 + +return: ; preds = %if.else, %if.then + %retval.0 = phi i32 [ %add, %if.then ], [ %rem1, %if.else ], !dbg !59 + ret i32 %retval.0, !dbg !60 +} + +; Function Attrs: nofree nounwind uwtable +define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #1 !dbg !61 !prof !73 { +entry: + call void @llvm.dbg.value(metadata i32 %argc, metadata !68, metadata !DIExpression()), !dbg !74 + call void @llvm.dbg.value(metadata i8** %argv, metadata !69, metadata !DIExpression()), !dbg !74 + call void @llvm.dbg.value(metadata i32 0, metadata !70, metadata !DIExpression()), !dbg !74 + call void @llvm.dbg.value(metadata i32 0, metadata !71, metadata !DIExpression()), !dbg !75 + br label %for.body, !dbg !76 + +for.cond.cleanup: ; preds = %for.body + call void @llvm.dbg.value(metadata i32 %add, metadata !70, metadata !DIExpression()), !dbg !74 + %call1 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %add), !dbg !77 + ret i32 0, !dbg !78 + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %total.07 = phi i32 [ 0, %entry ], [ %add, %for.body ] + call void @llvm.dbg.value(metadata i32 %i.08, metadata !71, metadata !DIExpression()), !dbg !75 + call void @llvm.dbg.value(metadata i32 %total.07, metadata !70, metadata !DIExpression()), !dbg !74 + %call = tail call i32 @foo(i32 %i.08), !dbg !79 + %add = add nsw i32 %call, %total.07, !dbg !82 + call void @llvm.dbg.value(metadata i32 %add, metadata !70, metadata !DIExpression()), !dbg !74 + %inc = add nuw nsw i32 %i.08, 1, !dbg !83 + call void @llvm.dbg.value(metadata i32 %inc, metadata !71, metadata !DIExpression()), !dbg !75 + %exitcond.not = icmp eq i32 %inc, 1000, !dbg !84 + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !76, !prof !85, !llvm.loop !86 +} + +; Function Attrs: nofree nounwind +declare dso_local noundef i32 @printf(i8* nocapture noundef readonly, ...) local_unnamed_addr #2 + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { inlinehint noinline norecurse nounwind readnone uwtable "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nofree nounwind uwtable "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nofree nounwind "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6, !35} +!llvm.ident = !{!39} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0 (git@github.com:llvm/llvm-project.git c9d6fe6f7d84f5b1a0bdbe502ebc3c8035722fdb)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "split_functions.c", directory: "/home/llvm-dev/working/llvm-project/build") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 1, !"ProfileSummary", !7} +!7 = !{!8, !9, !10, !11, !12, !13, !14, !15, !16, !17} +!8 = !{!"ProfileFormat", !"InstrProf"} +!9 = !{!"TotalCount", i64 2001} +!10 = !{!"MaxCount", i64 1000} +!11 = !{!"MaxInternalCount", i64 10} +!12 = !{!"MaxFunctionCount", i64 1000} +!13 = !{!"NumCounts", i64 4} +!14 = !{!"NumFunctions", i64 2} +!15 = !{!"IsPartialProfile", i64 0} +!16 = !{!"PartialProfileRatio", double 0.000000e+00} +!17 = !{!"DetailedSummary", !18} +!18 = !{!19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34} +!19 = !{i32 10000, i64 1000, i32 1} +!20 = !{i32 100000, i64 1000, i32 1} +!21 = !{i32 200000, i64 1000, i32 1} +!22 = !{i32 300000, i64 1000, i32 1} +!23 = !{i32 400000, i64 1000, i32 1} +!24 = !{i32 500000, i64 1000, i32 1} +!25 = !{i32 600000, i64 990, i32 2} +!26 = !{i32 700000, i64 990, i32 2} +!27 = !{i32 800000, i64 990, i32 2} +!28 = !{i32 900000, i64 990, i32 2} +!29 = !{i32 950000, i64 990, i32 2} +!30 = !{i32 990000, i64 990, i32 2} +!31 = !{i32 999000, i64 10, i32 3} +!32 = !{i32 999900, i64 10, i32 3} +!33 = !{i32 999990, i64 10, i32 3} +!34 = !{i32 999999, i64 10, i32 3} +!35 = !{i32 5, !"CG Profile", !36} +!36 = !{!37, !38} +!37 = !{i32 (i32, i8**)* @main, i32 (i8*, ...)* @printf, i64 1} +!38 = !{i32 (i32, i8**)* @main, i32 (i32)* @foo, i64 1001} +!39 = !{!"clang version 12.0.0 (git@github.com:llvm/llvm-project.git c9d6fe6f7d84f5b1a0bdbe502ebc3c8035722fdb)"} +!40 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !41, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !44) +!41 = !DISubroutineType(types: !42) +!42 = !{!43, !43} +!43 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!44 = !{!45} +!45 = !DILocalVariable(name: "i", arg: 1, scope: !40, file: !1, line: 3, type: !43) +!46 = !{!"function_entry_count", i64 1000} +!47 = !DILocation(line: 0, scope: !40) +!48 = !DILocation(line: 4, column: 9, scope: !49) +!49 = distinct !DILexicalBlock(scope: !40, file: !1, line: 4, column: 7) +!50 = !DILocation(line: 4, column: 7, scope: !40) +!51 = !{!"branch_weights", i32 10, i32 990} +!52 = !DILocation(line: 5, column: 14, scope: !53) +!53 = distinct !DILexicalBlock(scope: !49, file: !1, line: 4, column: 16) +!54 = !DILocation(line: 5, column: 5, scope: !53) +!55 = !DILocation(line: 7, column: 14, scope: !56) +!56 = distinct !DILexicalBlock(scope: !49, file: !1, line: 6, column: 10) +!57 = !DILocation(line: 7, column: 19, scope: !56) +!58 = !DILocation(line: 7, column: 5, scope: !56) +!59 = !DILocation(line: 0, scope: !49) +!60 = !DILocation(line: 9, column: 1, scope: !40) +!61 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 12, type: !62, scopeLine: 12, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !67) +!62 = !DISubroutineType(types: !63) +!63 = !{!43, !43, !64} +!64 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !65, size: 64) +!65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !66, size: 64) +!66 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!67 = !{!68, !69, !70, !71} +!68 = !DILocalVariable(name: "argc", arg: 1, scope: !61, file: !1, line: 12, type: !43) +!69 = !DILocalVariable(name: "argv", arg: 2, scope: !61, file: !1, line: 12, type: !64) +!70 = !DILocalVariable(name: "total", scope: !61, file: !1, line: 13, type: !43) +!71 = !DILocalVariable(name: "i", scope: !72, file: !1, line: 14, type: !43) +!72 = distinct !DILexicalBlock(scope: !61, file: !1, line: 14, column: 3) +!73 = !{!"function_entry_count", i64 1} +!74 = !DILocation(line: 0, scope: !61) +!75 = !DILocation(line: 0, scope: !72) +!76 = !DILocation(line: 14, column: 3, scope: !72) +!77 = !DILocation(line: 17, column: 3, scope: !61) +!78 = !DILocation(line: 18, column: 1, scope: !61) +!79 = !DILocation(line: 15, column: 14, scope: !80) +!80 = distinct !DILexicalBlock(scope: !81, file: !1, line: 14, column: 34) +!81 = distinct !DILexicalBlock(scope: !72, file: !1, line: 14, column: 3) +!82 = !DILocation(line: 15, column: 11, scope: !80) +!83 = !DILocation(line: 14, column: 29, scope: !81) +!84 = !DILocation(line: 14, column: 21, scope: !81) +!85 = !{!"branch_weights", i32 1, i32 1000} +!86 = distinct !{!86, !76, !87} +!87 = !DILocation(line: 16, column: 3, scope: !72)