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
14int __llvm_profile_runtime = 0;
15int __llvm_profile_write_file();
16void __llvm_profile_reset_counters(void);
17void __llvm_profile_merge_from_buffer(const char *, uint64_t);
18void __llvm_profile_set_filename(const char *);
19struct __llvm_profile_data;
20struct ValueProfData;
21void lprofMergeValueProfData(struct ValueProfData *, struct __llvm_profile_data *);
22/* Force the vp merger module to be linked in.  */
23void *Dummy = &lprofMergeValueProfData;
24
25void callee1() {}
26void callee2() {}
27void callee3() {}
28
29typedef void (*FP)(void);
30FP Fps[3] = {callee1, callee2, callee3};
31
32void 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 */
47void bar(void) {
48  int I;
49  for (I = 0; I < 20; I++)
50    Fps[I % 3]();
51}
52
53int 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