1 // RUN: %clang_profgen -mllvm --enable-value-profiling=true -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=3 -O2 -o %t %s
2 // RUN: %run %t %t.profraw
3 // RUN: llvm-profdata merge -o %t.profdata %t.profraw
4 // RUN: llvm-profdata show --all-functions --counts --ic-targets %t.profdata > %t.profdump
5 // RUN: FileCheck --input-file %t.profdump  %s --check-prefix=FOO
6 // RUN: FileCheck --input-file %t.profdump  %s --check-prefix=BAR
7 
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 
14 int __llvm_profile_runtime = 0;
15 int __llvm_profile_write_file();
16 void __llvm_profile_reset_counters(void);
17 void __llvm_profile_merge_from_buffer(const char *, uint64_t);
18 void __llvm_profile_set_filename(const char *);
19 struct __llvm_profile_data;
20 struct ValueProfData;
21 void lprofMergeValueProfData(struct ValueProfData *, struct __llvm_profile_data *);
22 /* Force the vp merger module to be linked in.  */
23 void *Dummy = &lprofMergeValueProfData;
24 
callee1()25 void callee1() {}
callee2()26 void callee2() {}
callee3()27 void callee3() {}
28 
29 typedef void (*FP)(void);
30 FP Fps[3] = {callee1, callee2, callee3};
31 
foo(int N)32 void foo(int N) {
33   int I, J;
34   for (I = 0; I < 3; I++)
35     for (J = 0; J < I * 2 + 1; J++)
36       Fps[I]();
37 
38   if (N < 2)
39     return;
40 
41   for (I = 0; I < 3; I++)
42     for (J = 0; J < I * 2 + 1; J++)
43       Fps[2 - I]();
44 }
45 
46 /* This function is not profiled */
bar(void)47 void bar(void) {
48   int I;
49   for (I = 0; I < 20; I++)
50     Fps[I % 3]();
51 }
52 
main(int argc,const char * argv[])53 int main(int argc, const char *argv[]) {
54   int i;
55   if (argc < 2)
56     return 1;
57 
58   const char *FileN = argv[1];
59   __llvm_profile_set_filename(FileN);
60   /* Start profiling. */
61   __llvm_profile_reset_counters();
62   foo(1);
63   /* End profiling by freezing counters and
64    * dump them to the file. */
65   if (__llvm_profile_write_file())
66     return 1;
67 
68   /* Read profile data into buffer. */
69   FILE *File = fopen(FileN, "r");
70   if (!File)
71     return 1;
72   fseek(File, 0, SEEK_END);
73   uint64_t Size = ftell(File);
74   fseek(File, 0, SEEK_SET);
75   char *Buffer = (char *)malloc(Size);
76   if (Size != fread(Buffer, 1, Size, File))
77     return 1;
78   fclose(File);
79 
80   /* Its profile will be discarded. */
81   for (i = 0; i < 10; i++)
82     bar();
83 
84   /* Start profiling again and merge in previously
85      saved counters in buffer. */
86   __llvm_profile_reset_counters();
87   __llvm_profile_merge_from_buffer(Buffer, Size);
88   foo(2);
89   /* End profiling. */
90   truncate(FileN, 0);
91   if (__llvm_profile_write_file())
92     return 1;
93 
94   /* Its profile will be discarded. */
95   bar();
96 
97   return 0;
98 }
99 
100 // FOO-LABEL:  foo:
101 // FOO:    Indirect Target Results:
102 // FOO-NEXT:	[ 0, callee3, 10 ]
103 // FOO-NEXT:	[ 0, callee2, 6 ]
104 // FOO-NEXT:	[ 0, callee1, 2 ]
105 // FOO-NEXT:	[ 1, callee1, 5 ]
106 // FOO-NEXT:	[ 1, callee2, 3 ]
107 // FOO-NEXT:	[ 1, callee3, 1 ]
108 
109 // BAR-LABEL: bar:
110 // BAR:         [ 0, callee1, 0 ]
111 // BAR-NEXT:    [ 0, callee2, 0 ]
112 // BAR-NEXT:    [ 0, callee3, 0 ]
113 
114