brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · ffd9676 Raw
161 lines · c
1// REQUIRES: target={{.*windows-msvc.*}}2// REQUIRES: lld-available3 4// Fails on Windows on Arm for unknown reasons.5// UNSUPPORTED: target=aarch64-pc-windows-msvc6 7// Test the online merging mode (%m) along with continuous mode (%c).8//9// Split files & cd into a temporary directory.10// RUN: rm -rf %t.dir && split-file %s %t.dir && cd %t.dir11//12// Create two DLLs and a driver program that uses them.13// RUN: %clang_pgogen=%t.dir/profdir -fprofile-continuous -fprofile-update=atomic foo.c -fuse-ld=lld -Wl,-dll -o %t.dir/foo.dll14// RUN: %clang_pgogen=%t.dir/profdir -fprofile-continuous -fprofile-update=atomic bar.c -fuse-ld=lld -Wl,-dll -o %t.dir/bar.dll15// RUN: %clang_pgogen=%t.dir/profdir -fprofile-continuous -fprofile-update=atomic main.c -o main.exe %t.dir/foo.lib %t.dir/bar.lib -fuse-ld=lld16//17// === Round 1 ===18// Test merging+continuous mode without any file contention.19//20// RUN: %run %t.dir/main.exe nospawn21// RUN: llvm-profdata merge -o %t.profdata %t.dir/profdir22// RUN: llvm-profdata show --counts --all-functions %t.profdata | FileCheck %s -check-prefix=ROUND123 24// ROUND1-LABEL: Counters:25// ROUND1-DAG:   foo:26// ROUND1-DAG:     Hash: 0x{{.*}}27// ROUND1-DAG:     Counters: 128// ROUND1-DAG:     Block counts: [1]29// ROUND1-DAG:   bar:30// ROUND1-DAG:     Hash: 0x{{.*}}31// ROUND1-DAG:     Counters: 132// ROUND1-DAG:     Block counts: [1]33// ROUND1-DAG:   main:34// ROUND1-DAG:     Hash: 0x{{.*}}35// ROUND1-LABEL: Instrumentation level: IR36//37// === Round 2 ===38// Test merging+continuous mode with some file contention.39//40// RUN: %run %t.dir/main.exe spawn41// RUN: llvm-profdata merge -o %t.profdata %t.dir/profdir42// RUN: llvm-profdata show --counts --all-functions %t.profdata | FileCheck %s -check-prefix=ROUND243 44// ROUND2-LABEL: Counters:45// ROUND2-DAG:   foo:46// ROUND2-DAG:     Hash: 0x{{.*}}47// ROUND2-DAG:     Counters: 148// ROUND2-DAG:     Block counts: [97]49// ROUND2-DAG:   bar:50// ROUND2-DAG:     Hash: 0x{{.*}}51// ROUND2-DAG:     Counters: 152// ROUND2-DAG:     Block counts: [97]53// ROUND2-DAG:   main:54// ROUND2-DAG:     Hash: 0x{{.*}}55// ROUND2-LABEL: Instrumentation level: IR56 57//--- foo.c58__declspec(dllexport) void foo(void) {}59 60//--- bar.c61__declspec(dllexport) void bar(void) {}62 63//--- main.c64#include <stdio.h>65#include <string.h>66#include <windows.h>67 68 69const int num_child_procs_to_spawn = 32;70 71extern int __llvm_profile_is_continuous_mode_enabled(void);72extern char *__llvm_profile_get_filename(void);73 74__declspec(dllimport) void foo(void);75__declspec(dllimport) void bar(void);76 77// Change to "#define" for debug output.78#undef DEBUG_TEST79 80#ifdef DEBUG_TEST81#  define DEBUG(...) fprintf(stderr, __VA_ARGS__);82#else83#  define DEBUG(...)84#endif85 86int main(int argc, char *const argv[]) {87  if (argc < 2) {88    DEBUG("Requires at least one argument.\n");89    return 1;90  }91  if (strcmp(argv[1], "nospawn") == 0) {92    DEBUG(93        "Hello from child (pid = %lu, cont-mode-enabled = %d, profile = %s).\n",94        GetCurrentProcessId(), __llvm_profile_is_continuous_mode_enabled(),95        __llvm_profile_get_filename());96 97    foo();98    bar();99    return 0;100  } else if (strcmp(argv[1], "spawn") == 0) {101    // This is the start of Round 2.102    // Expect Counts[dsoX] = 1, as this was the state at the end of Round 1.103    int I;104    HANDLE child_pids[num_child_procs_to_spawn];105    for (I = 0; I < num_child_procs_to_spawn; ++I) {106      foo(); // Counts[dsoX] += 2 * num_child_procs_to_spawn107      bar();108 109      DEBUG("Spawning child with argv = {%s, %s, NULL} and envp = {%s, NULL}\n",110            child_argv[0], child_argv[1], child_envp[0]);111 112      // Start the child process.113      STARTUPINFO si;114      ZeroMemory(&si, sizeof(si));115      PROCESS_INFORMATION pi;116      ZeroMemory(&pi, sizeof(pi));117      if (!CreateProcess(NULL,               // No module name (use command line)118                         "main.exe nospawn", // Command line119                         NULL,               // Process handle not inheritable120                         NULL,               // Thread handle not inheritable121                         FALSE,              // Set handle inheritance to FALSE122                         0,                  // No creation flags123                         NULL,               // Use parent's environment block124                         NULL,               // Use parent's starting directory125                         &si,                // Pointer to STARTUPINFO structure126                         &pi)                // Pointer to PROCESS_INFORMATION structure127      ) {128        fprintf(stderr, "Child %d could not be spawned: %lu\n", I,129                GetLastError());130        return 1;131      }132      child_pids[I] = pi.hProcess;133 134      DEBUG("Spawned child %d (pid = %zu).\n", I, pi.dwProcessId);135    }136    for (I = 0; I < num_child_procs_to_spawn; ++I) {137      foo(); // Counts[dsoX] += num_child_procs_to_spawn138      bar();139 140      DWORD exit_code;141      WaitForSingleObject(child_pids[I], INFINITE);142      if (!GetExitCodeProcess(child_pids[I], &exit_code)) {143        fprintf(stderr, "Failed to get exit code of child %d.\n", I);144        return 1;145      }146      if (exit_code != 0) {147        fprintf(stderr, "Child %d did not exit with code 0.\n", I);148        return 1;149      }150    }151 152    // At the end of Round 2, we have:153    // Counts[dsoX] = 1 + (2 * num_child_procs_to_spawn) + num_child_procs_to_spawn154    //              = 97155 156    return 0;157  }158 159  return 1;160}161