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