#!/bin/bash if [ $# -lt 2 ]; then echo "Path to clang and llvm-profdata required!" echo "Usage: update_memprof_inputs.sh /path/to/updated/clang /path/to/updated/llvm-profdata" exit 1 else CLANG=$1 LLVMPROFDATA=$2 fi # Allows the script to be invoked from other directories. OUTDIR=$(dirname $(realpath -s $0)) # Note that changes in the code below which affect relative line number # offsets of calls from their parent function can affect callsite matching in # the LLVM IR. cat > ${OUTDIR}/memprof.cc << EOF #include #include #include char *foo() { return new char[10]; } char *foo2() { return foo(); } char *bar() { return foo2(); } char *baz() { return foo2(); } char *recurse(unsigned n) { if (!n) return foo(); return recurse(n-1); } int main(int argc, char **argv) { // Test allocations with different combinations of stack contexts and // coldness (based on lifetime, since they are all accessed a single time // per byte via the memset). char *a = new char[10]; char *b = new char[10]; char *c = foo(); char *d = foo(); char *e = bar(); char *f = baz(); memset(a, 0, 10); memset(b, 0, 10); memset(c, 0, 10); memset(d, 0, 10); memset(e, 0, 10); memset(f, 0, 10); // a and c have short lifetimes delete[] a; delete[] c; // b, d, e, and f have long lifetimes and will be detected as cold by default. sleep(200); delete[] b; delete[] d; delete[] e; delete[] f; // Loop ensures the two calls to recurse have stack contexts that only differ // in one level of recursion. We should get two stack contexts reflecting the // different levels of recursion and different allocation behavior (since the // first has a very long lifetime and the second has a short lifetime). for (unsigned i = 0; i < 2; i++) { char *g = recurse(i + 3); memset(g, 0, 10); if (!i) sleep(200); delete[] g; } return 0; } EOF COMMON_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" ${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof.cc -o ${OUTDIR}/memprof.exe env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof.exe > ${OUTDIR}/memprof.memprofraw # Generate another profile without any column numbers. ${CLANG} ${COMMON_FLAGS} -gno-column-info -fmemory-profile ${OUTDIR}/memprof.cc -o ${OUTDIR}/memprof.nocolinfo.exe env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof.nocolinfo.exe > ${OUTDIR}/memprof.nocolinfo.memprofraw ${CLANG} ${COMMON_FLAGS} -fprofile-generate=. \ ${OUTDIR}/memprof.cc -o ${OUTDIR}/pgo.exe env LLVM_PROFILE_FILE=${OUTDIR}/memprof_pgo.profraw ${OUTDIR}/pgo.exe ${LLVMPROFDATA} merge --text ${OUTDIR}/memprof_pgo.profraw -o ${OUTDIR}/memprof_pgo.proftext rm ${OUTDIR}/memprof.cc rm ${OUTDIR}/pgo.exe rm ${OUTDIR}/memprof_pgo.profraw cat > ${OUTDIR}/memprof_internal_linkage.cc << EOF #include #include static void foo() { int *a = new int[5]; memset(a, 0, 5); } int main(int argc, char **argv) { foo(); return 0; } EOF ${CLANG} ${COMMON_FLAGS} -fmemory-profile -funique-internal-linkage-names ${OUTDIR}/memprof_internal_linkage.cc -o ${OUTDIR}/memprof_internal_linkage.exe env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof_internal_linkage.exe > ${OUTDIR}/memprof_internal_linkage.memprofraw rm ${OUTDIR}/memprof_internal_linkage.cc cat > ${OUTDIR}/memprof_loop_unroll_a.cc << EOF int* a[2]; extern void foo(); int main() { foo(); for (int i = 0; i < 1000000; ++i) { *a[0] = 1; } return 0; } EOF cat > ${OUTDIR}/memprof_loop_unroll_b.cc << EOF #include extern int* a[2]; void foo() { for (int i = 0; i < 2; ++i) { a[i] = new int[1]; } } EOF ${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof_loop_unroll_a.cc -O0 -o ${OUTDIR}/memprof_loop_unroll_a.o -c ${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof_loop_unroll_b.cc -O3 -o ${OUTDIR}/memprof_loop_unroll_b.o -c ${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof_loop_unroll_a.o ${OUTDIR}/memprof_loop_unroll_b.o -o ${OUTDIR}/memprof_loop_unroll.exe env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof_loop_unroll.exe > ${OUTDIR}/memprof_loop_unroll.memprofraw rm ${OUTDIR}/memprof_loop_unroll_a.cc rm ${OUTDIR}/memprof_loop_unroll_a.o rm ${OUTDIR}/memprof_loop_unroll_b.cc rm ${OUTDIR}/memprof_loop_unroll_b.o