Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -208,6 +208,7 @@ #================================ include(CheckIncludeFile) check_include_file(unwind.h HAVE_UNWIND_H) +check_include_file(mpi.h HAVE_MPI_H) include(config-ix) Index: lib/profile/CMakeLists.txt =================================================================== --- lib/profile/CMakeLists.txt +++ lib/profile/CMakeLists.txt @@ -36,7 +36,9 @@ InstrProfilingPlatformDarwin.c InstrProfilingPlatformLinux.c InstrProfilingPlatformOther.c + InstrProfilingReduce.c InstrProfilingRuntime.cc + InstrProfilingStub.c InstrProfilingUtil.c) if(WIN32) @@ -55,6 +57,12 @@ -DCOMPILER_RT_HAS_ATOMICS=1) endif() +if(HAVE_MPI_H) + set(EXTRA_FLAGS + ${EXTRA_FLAGS} + -DHAVE_MPI_H=1) +endif() + if(APPLE) add_compiler_rt_runtime(clang_rt.profile STATIC Index: lib/profile/InstrProfilingFile.c =================================================================== --- lib/profile/InstrProfilingFile.c +++ lib/profile/InstrProfilingFile.c @@ -15,8 +15,19 @@ #include #include +#ifndef _MSC_VER +#include +#include +#include +#include +#endif + #define UNCONST(ptr) ((void *)(uintptr_t)(ptr)) +#ifdef HAVE_MPI_H +COMPILER_RT_VISIBILITY extern int __llvm_write_prof_data; +#endif + /* Return 1 if there is an error, otherwise return 0. */ static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs, void **WriterCtx) { @@ -72,7 +83,11 @@ static void truncateCurrentFile(void) { const char *Filename; +#ifdef _MSC_VER FILE *File; +#else + int File; +#endif Filename = __llvm_profile_CurrentFilename; if (!Filename || !Filename[0]) @@ -86,11 +101,20 @@ free(Copy); } +#ifdef _MSC_VER /* Truncate the file. Later we'll reopen and append. */ File = fopen(Filename, "w"); if (!File) return; fclose(File); +#else + /* O_CREAT is not included to avoid creating empty files. + In MPI applications, a file will only be created by one process */ + File = open(Filename, O_WRONLY | O_TRUNC); + if (File == -1) + return; + close(File); +#endif } static void setFilename(const char *Filename, int OwnsFilename) { @@ -216,6 +240,11 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_file(void) { + +#ifdef HAVE_MPI_H + if (!__llvm_write_prof_data) + return 0; +#endif int rc; GetEnvHook = &getenv; Index: lib/profile/InstrProfilingReduce.c =================================================================== --- /dev/null +++ lib/profile/InstrProfilingReduce.c @@ -0,0 +1,34 @@ +/*===- InstrProfilingReduce.c - Support library for applications using MPI ===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include +#include + +#ifdef HAVE_MPI_H +#include +COMPILER_RT_VISIBILITY int __llvm_write_prof_data = 1; +COMPILER_RT_VISIBILITY int MPI_Finalize() { + int Rank; + uint64_t *CountersBegin = __llvm_profile_begin_counters(); + uint64_t *CountersEnd = __llvm_profile_end_counters(); + uint64_t CountersSize = CountersEnd - CountersBegin; + + MPI_Comm_rank(MPI_COMM_WORLD, &Rank); + if (Rank) { + MPI_Reduce(CountersBegin, NULL, CountersSize, MPI_UINT64_T, MPI_SUM, + 0, MPI_COMM_WORLD); + __llvm_write_prof_data = 0; + } else + MPI_Reduce(MPI_IN_PLACE, CountersBegin, CountersSize, MPI_UINT64_T, MPI_SUM, + 0, MPI_COMM_WORLD); + return PMPI_Finalize(); +} + +#endif + Index: lib/profile/InstrProfilingStub.c =================================================================== --- /dev/null +++ lib/profile/InstrProfilingStub.c @@ -0,0 +1,14 @@ +/*===- InstrProfilingStub.c - Stubs for applications not using MPI --------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include + +void MPI_Comm_rank(void *Comm, int *Rank) { abort(); } +void MPI_Reduce() { abort(); } +void PMPI_Finalize() { abort(); } Index: test/profile/instrprof-reduce.c =================================================================== --- /dev/null +++ test/profile/instrprof-reduce.c @@ -0,0 +1,24 @@ +// RUN: %clang_profgen -o %t -O3 %s +// RUN: rm -f %t.profraw +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t 0 +// RUN: test -e %t.profraw +// RUN: rm -f %t.profraw +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t 1 +// RUN: test ! -e %t.profraw +// REQUIRES: shell + +#include +#include +int ThisRank; +int MPI_Comm_rank(void *Comm, int *Rank) { *Rank = ThisRank; return 0; } +int MPI_Reduce() { return 0; } +int PMPI_Finalize() { return 0; } +int MPI_Finalize(); + +int main(int argc, const char *argv[]) { +printf("in main\n"); + ThisRank = atoi(argv[1]); + MPI_Finalize(); + return 0; +} +