xref: /llvm-project/llvm/test/Transforms/PGOProfile/Inputs/update_memprof_inputs.sh (revision a03343daa6e7a44531e06c8897d6c6d4a46cd430)
1#!/bin/bash
2
3if [ $# -lt 2 ]; then
4  echo "Path to clang and llvm-profdata required!"
5  echo "Usage: update_memprof_inputs.sh /path/to/updated/clang /path/to/updated/llvm-profdata"
6  exit 1
7else
8  CLANG=$1
9  LLVMPROFDATA=$2
10fi
11
12# Allows the script to be invoked from other directories.
13OUTDIR=$(dirname $(realpath -s $0))
14
15# Note that changes in the code below which affect relative line number
16# offsets of calls from their parent function can affect callsite matching in
17# the LLVM IR.
18cat > ${OUTDIR}/memprof.cc << EOF
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22char *foo() {
23  return new char[10];
24}
25char *foo2() {
26  return foo();
27}
28char *bar() {
29  return foo2();
30}
31char *baz() {
32  return foo2();
33}
34char *recurse(unsigned n) {
35  if (!n)
36    return foo();
37  return recurse(n-1);
38}
39int main(int argc, char **argv) {
40  // Test allocations with different combinations of stack contexts and
41  // coldness (based on lifetime, since they are all accessed a single time
42  // per byte via the memset).
43  char *a = new char[10];
44  char *b = new char[10];
45  char *c = foo();
46  char *d = foo();
47  char *e = bar();
48  char *f = baz();
49  memset(a, 0, 10);
50  memset(b, 0, 10);
51  memset(c, 0, 10);
52  memset(d, 0, 10);
53  memset(e, 0, 10);
54  memset(f, 0, 10);
55  // a and c have short lifetimes
56  delete[] a;
57  delete[] c;
58  // b, d, e, and f have long lifetimes and will be detected as cold by default.
59  sleep(200);
60  delete[] b;
61  delete[] d;
62  delete[] e;
63  delete[] f;
64
65  // Loop ensures the two calls to recurse have stack contexts that only differ
66  // in one level of recursion. We should get two stack contexts reflecting the
67  // different levels of recursion and different allocation behavior (since the
68  // first has a very long lifetime and the second has a short lifetime).
69  for (unsigned i = 0; i < 2; i++) {
70    char *g = recurse(i + 3);
71    memset(g, 0, 10);
72    if (!i)
73      sleep(200);
74    delete[] g;
75  }
76  return 0;
77}
78EOF
79
80COMMON_FLAGS="-fuse-ld=lld -Wl,--no-rosegment -gmlt -fdebug-info-for-profiling -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -m64 -Wl,-build-id -no-pie"
81
82${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof.cc -o ${OUTDIR}/memprof.exe
83env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof.exe > ${OUTDIR}/memprof.memprofraw
84
85# Generate another profile without any column numbers.
86${CLANG} ${COMMON_FLAGS} -gno-column-info -fmemory-profile ${OUTDIR}/memprof.cc -o ${OUTDIR}/memprof.nocolinfo.exe
87env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof.nocolinfo.exe > ${OUTDIR}/memprof.nocolinfo.memprofraw
88
89${CLANG} ${COMMON_FLAGS} -fprofile-generate=. \
90  ${OUTDIR}/memprof.cc -o ${OUTDIR}/pgo.exe
91env LLVM_PROFILE_FILE=${OUTDIR}/memprof_pgo.profraw ${OUTDIR}/pgo.exe
92${LLVMPROFDATA} merge --text ${OUTDIR}/memprof_pgo.profraw -o ${OUTDIR}/memprof_pgo.proftext
93
94rm ${OUTDIR}/memprof.cc
95rm ${OUTDIR}/pgo.exe
96rm ${OUTDIR}/memprof_pgo.profraw
97
98cat > ${OUTDIR}/memprof_internal_linkage.cc << EOF
99#include <cstring>
100#include <unistd.h>
101static void foo() {
102  int *a = new int[5];
103  memset(a, 0, 5);
104}
105int main(int argc, char **argv) {
106  foo();
107  return 0;
108}
109EOF
110
111${CLANG} ${COMMON_FLAGS} -fmemory-profile -funique-internal-linkage-names ${OUTDIR}/memprof_internal_linkage.cc -o ${OUTDIR}/memprof_internal_linkage.exe
112env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof_internal_linkage.exe > ${OUTDIR}/memprof_internal_linkage.memprofraw
113
114rm ${OUTDIR}/memprof_internal_linkage.cc
115
116cat > ${OUTDIR}/memprof_loop_unroll_a.cc << EOF
117int* a[2];
118extern void foo();
119int main() {
120    foo();
121    for (int i = 0; i < 1000000; ++i) {
122        *a[0] = 1;
123    }
124    return 0;
125}
126EOF
127cat > ${OUTDIR}/memprof_loop_unroll_b.cc << EOF
128#include <string>
129extern int* a[2];
130void foo() {
131    for (int i = 0; i < 2; ++i) {
132        a[i] = new int[1];
133    }
134}
135EOF
136${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof_loop_unroll_a.cc -O0 -o ${OUTDIR}/memprof_loop_unroll_a.o -c
137${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof_loop_unroll_b.cc -O3 -o ${OUTDIR}/memprof_loop_unroll_b.o -c
138${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof_loop_unroll_a.o ${OUTDIR}/memprof_loop_unroll_b.o -o ${OUTDIR}/memprof_loop_unroll.exe
139env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof_loop_unroll.exe > ${OUTDIR}/memprof_loop_unroll.memprofraw
140rm ${OUTDIR}/memprof_loop_unroll_a.cc
141rm ${OUTDIR}/memprof_loop_unroll_a.o
142rm ${OUTDIR}/memprof_loop_unroll_b.cc
143rm ${OUTDIR}/memprof_loop_unroll_b.o