This is probably more of a comment on the compare_bench.py side of things, but here goes anyway...

When comparing two results, both the percentage and absolute differences can be very important. It is very easy to be misled by percentages. It is harder to be misled with absolute differences.

For example, I think it is more insightful to see something like this for the comparison:

Comparing ./util_smartptr.native.out to ./util_smartptr.libcxx.out
Benchmark                          Time           CPU
-----------------------------------------------------
BM_SharedPtrCreateDestroy         -16 ns (-26%) -16 ns (-26%)
BM_SharedPtrIncDecRef             +0 ns (+0%)   +0 ns (+0%)
BM_WeakPtrIncDecRef               +6 ns (+21%)  +6 ns (+21%)

This presentation makes it easier to evaluate the significance of shifted costs. The shared_ptr changes moved some costs around, and this benchmark shows that 16 ns left one area, and turned into 6 ns elsewhere. The percentages mask that insight.

I've been in benchmarking situations where one function's time is reduced by 5%, and another function increases by 100%. Some managers started panicking because of it. In actuality, 5 ms was shaved off of a 100 ms operation that was in the inner loop. The 5 ms was moved into the outer loop which previously took 5 ms.


On 8/9/2016 1:56 PM, Eric Fiselier via cfe-commits wrote:
Author: ericwf
Date: Tue Aug  9 13:56:48 2016
New Revision: 278147

URL: http://llvm.org/viewvc/llvm-project?rev=278147&view=rev
Log:
Update in-tree Google Benchmark to current ToT.

I've put some work into the Google Benchmark library in order to make it easier
to benchmark libc++. These changes have already been upstreamed into
Google Benchmark and this patch applies the changes to the in-tree version.

The main improvement in the addition of a 'compare_bench.py' script which
makes it very easy to compare benchmarks. For example to compare the native
STL to libc++ you would run:

`$ compare_bench.py ./util_smartptr.native.out ./util_smartptr.libcxx.out`

And the output would look like:

RUNNING: ./util_smartptr.native.out
Benchmark                          Time           CPU Iterations
----------------------------------------------------------------
BM_SharedPtrCreateDestroy         62 ns         62 ns   10937500
BM_SharedPtrIncDecRef             31 ns         31 ns   23972603
BM_WeakPtrIncDecRef               28 ns         28 ns   23648649
RUNNING: ./util_smartptr.libcxx.out
Benchmark                          Time           CPU Iterations
----------------------------------------------------------------
BM_SharedPtrCreateDestroy         46 ns         46 ns   14957265
BM_SharedPtrIncDecRef             31 ns         31 ns   22435897
BM_WeakPtrIncDecRef               34 ns         34 ns   21084337
Comparing ./util_smartptr.native.out to ./util_smartptr.libcxx.out
Benchmark                          Time           CPU
-----------------------------------------------------
BM_SharedPtrCreateDestroy         -0.26         -0.26
BM_SharedPtrIncDecRef             +0.00         +0.00
BM_WeakPtrIncDecRef               +0.21         +0.21

Added:
     libcxx/trunk/utils/google-benchmark/test/multiple_ranges_test.cc
     libcxx/trunk/utils/google-benchmark/test/register_benchmark_test.cc
     libcxx/trunk/utils/google-benchmark/tools/
     libcxx/trunk/utils/google-benchmark/tools/compare_bench.py
     libcxx/trunk/utils/google-benchmark/tools/gbench/
     libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/
     libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json
     libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json
     libcxx/trunk/utils/google-benchmark/tools/gbench/__init__.py
     libcxx/trunk/utils/google-benchmark/tools/gbench/report.py
     libcxx/trunk/utils/google-benchmark/tools/gbench/util.py
Modified:
     libcxx/trunk/benchmarks/CMakeLists.txt
     libcxx/trunk/benchmarks/ContainerBenchmarks.hpp
     libcxx/trunk/benchmarks/algorithms.bench.cpp
     libcxx/trunk/benchmarks/unordered_set_operations.bench.cpp
     libcxx/trunk/utils/google-benchmark/AUTHORS
     libcxx/trunk/utils/google-benchmark/README.md
     libcxx/trunk/utils/google-benchmark/include/benchmark/benchmark_api.h
     libcxx/trunk/utils/google-benchmark/include/benchmark/macros.h
     libcxx/trunk/utils/google-benchmark/include/benchmark/reporter.h
     libcxx/trunk/utils/google-benchmark/src/benchmark.cc
     libcxx/trunk/utils/google-benchmark/src/colorprint.cc
     libcxx/trunk/utils/google-benchmark/src/colorprint.h
     libcxx/trunk/utils/google-benchmark/src/complexity.cc
     libcxx/trunk/utils/google-benchmark/src/console_reporter.cc
     libcxx/trunk/utils/google-benchmark/src/cycleclock.h
     libcxx/trunk/utils/google-benchmark/src/sysinfo.cc
     libcxx/trunk/utils/google-benchmark/test/CMakeLists.txt
     libcxx/trunk/utils/google-benchmark/test/basic_test.cc
     libcxx/trunk/utils/google-benchmark/test/benchmark_test.cc
     libcxx/trunk/utils/google-benchmark/test/complexity_test.cc
     libcxx/trunk/utils/google-benchmark/test/fixture_test.cc
     libcxx/trunk/utils/google-benchmark/test/map_test.cc
     libcxx/trunk/utils/google-benchmark/test/options_test.cc
     libcxx/trunk/utils/google-benchmark/test/reporter_output_test.cc
     libcxx/trunk/utils/google-benchmark/test/skip_with_error_test.cc

Modified: libcxx/trunk/benchmarks/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/benchmarks/CMakeLists.txt?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/benchmarks/CMakeLists.txt (original)
+++ libcxx/trunk/benchmarks/CMakeLists.txt Tue Aug  9 13:56:48 2016
@@ -87,7 +87,12 @@ macro(add_benchmark_test name source_fil
    add_executable(${libcxx_target} EXCLUDE_FROM_ALL ${source_file})
    add_dependencies(${libcxx_target} cxx google-benchmark-libcxx)
    add_dependencies(libcxx-benchmarks ${libcxx_target})
-  target_link_libraries(${libcxx_target} cxx -lbenchmark)
+  if (LIBCXX_ENABLE_SHARED)
+    target_link_libraries(${libcxx_target} cxx_shared)
+  else()
+    target_link_libraries(${libcxx_target} cxx_static)
+  endif()
+  target_link_libraries(${libcxx_target} -lbenchmark)
    set_target_properties(${libcxx_target}
      PROPERTIES
            OUTPUT_NAME "${name}.libcxx.out"

Modified: libcxx/trunk/benchmarks/ContainerBenchmarks.hpp
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/benchmarks/ContainerBenchmarks.hpp?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/benchmarks/ContainerBenchmarks.hpp (original)
+++ libcxx/trunk/benchmarks/ContainerBenchmarks.hpp Tue Aug  9 13:56:48 2016
@@ -10,7 +10,7 @@ namespace ContainerBenchmarks {
template <class Container, class GenInputs>
  void BM_ConstructIterIter(benchmark::State& st, Container, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      const auto end = in.end();
      benchmark::DoNotOptimize(&in);
      while (st.KeepRunning()) {
@@ -21,7 +21,7 @@ void BM_ConstructIterIter(benchmark::Sta
template <class Container, class GenInputs>
  void BM_InsertValue(benchmark::State& st, Container c, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      const auto end = in.end();
      while (st.KeepRunning()) {
          c.clear();
@@ -34,7 +34,7 @@ void BM_InsertValue(benchmark::State& st
template <class Container, class GenInputs>
  void BM_InsertValueRehash(benchmark::State& st, Container c, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      const auto end = in.end();
      while (st.KeepRunning()) {
          c.clear();
@@ -49,7 +49,7 @@ void BM_InsertValueRehash(benchmark::Sta
template <class Container, class GenInputs>
  void BM_InsertDuplicate(benchmark::State& st, Container c, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      const auto end = in.end();
      c.insert(in.begin(), in.end());
      benchmark::DoNotOptimize(&c);
@@ -65,7 +65,7 @@ void BM_InsertDuplicate(benchmark::State
template <class Container, class GenInputs>
  void BM_EmplaceDuplicate(benchmark::State& st, Container c, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      const auto end = in.end();
      c.insert(in.begin(), in.end());
      benchmark::DoNotOptimize(&c);
@@ -80,7 +80,7 @@ void BM_EmplaceDuplicate(benchmark::Stat
template <class Container, class GenInputs>
  static void BM_Find(benchmark::State& st, Container c, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      c.insert(in.begin(), in.end());
      benchmark::DoNotOptimize(&(*c.begin()));
      const auto end = in.data() + in.size();
@@ -95,7 +95,7 @@ static void BM_Find(benchmark::State& st
  template <class Container, class GenInputs>
  static void BM_FindRehash(benchmark::State& st, Container c, GenInputs gen) {
      c.rehash(8);
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      c.insert(in.begin(), in.end());
      benchmark::DoNotOptimize(&(*c.begin()));
      const auto end = in.data() + in.size();

Modified: libcxx/trunk/benchmarks/algorithms.bench.cpp
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/benchmarks/algorithms.bench.cpp?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/benchmarks/algorithms.bench.cpp (original)
+++ libcxx/trunk/benchmarks/algorithms.bench.cpp Tue Aug  9 13:56:48 2016
@@ -10,7 +10,7 @@ constexpr std::size_t TestNumInputs = 10
  template <class GenInputs>
  void BM_Sort(benchmark::State& st, GenInputs gen) {
      using ValueType = typename decltype(gen(0))::value_type;
-    const auto in = gen(st.range_x());
+    const auto in = gen(st.range(0));
      std::vector<ValueType> inputs[5];
      auto reset_inputs = [&]() {
          for (auto& C : inputs) {

Modified: libcxx/trunk/benchmarks/unordered_set_operations.bench.cpp
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/benchmarks/unordered_set_operations.bench.cpp?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/benchmarks/unordered_set_operations.bench.cpp (original)
+++ libcxx/trunk/benchmarks/unordered_set_operations.bench.cpp Tue Aug  9 
13:56:48 2016
@@ -109,7 +109,7 @@ struct UInt64Hash2 {
template <class HashFn, class GenInputs>
  void BM_Hash(benchmark::State& st, HashFn fn, GenInputs gen) {
-    auto in = gen(st.range_x());
+    auto in = gen(st.range(0));
      const auto end = in.data() + in.size();
      std::size_t last_hash = 0;
      benchmark::DoNotOptimize(&last_hash);

Modified: libcxx/trunk/utils/google-benchmark/AUTHORS
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/AUTHORS?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/AUTHORS (original)
+++ libcxx/trunk/utils/google-benchmark/AUTHORS Tue Aug  9 13:56:48 2016
@@ -13,6 +13,7 @@ Arne Beer <a...@twobeer.de>
  Christopher Seymour <chris.j.seym...@hotmail.com>
  David Coeurjolly <david.coeurjo...@liris.cnrs.fr>
  Dominic Hamon <d...@stripysock.com>
+Eric Fiselier <e...@efcs.ca>
  Eugene Zhuk <eugene.z...@gmail.com>
  Evgeny Safronov <division...@gmail.com>
  Felix Homann <linuxau...@showlabor.de>

Modified: libcxx/trunk/utils/google-benchmark/README.md
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/README.md?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/README.md (original)
+++ libcxx/trunk/utils/google-benchmark/README.md Tue Aug  9 13:56:48 2016
@@ -40,13 +40,13 @@ measuring the speed of `memcpy()` calls
```c++
  static void BM_memcpy(benchmark::State& state) {
-  char* src = new char[state.range_x()];
-  char* dst = new char[state.range_x()];
-  memset(src, 'x', state.range_x());
+  char* src = new char[state.range(0)];
+  char* dst = new char[state.range(0)];
+  memset(src, 'x', state.range(0));
    while (state.KeepRunning())
-    memcpy(dst, src, state.range_x());
+    memcpy(dst, src, state.range(0));
    state.SetBytesProcessed(int64_t(state.iterations()) *
-                          int64_t(state.range_x()));
+                          int64_t(state.range(0)));
    delete[] src;
    delete[] dst;
  }
@@ -70,7 +70,7 @@ BENCHMARK(BM_memcpy)->RangeMultiplier(2)
  ```
  Now arguments generated are [ 8, 16, 32, 64, 128, 256, 512, 1024, 2k, 4k, 8k 
].
-You might have a benchmark that depends on two inputs. For example, the
+You might have a benchmark that depends on two or more inputs. For example, the
  following code defines a family of benchmarks for measuring the speed of set
  insertion.
@@ -78,21 +78,21 @@ insertion.
  static void BM_SetInsert(benchmark::State& state) {
    while (state.KeepRunning()) {
      state.PauseTiming();
-    std::set<int> data = ConstructRandomSet(state.range_x());
+    std::set<int> data = ConstructRandomSet(state.range(0));
      state.ResumeTiming();
-    for (int j = 0; j < state.range_y(); ++j)
+    for (int j = 0; j < state.range(1); ++j)
        data.insert(RandomNumber());
    }
  }
  BENCHMARK(BM_SetInsert)
-    ->ArgPair(1<<10, 1)
-    ->ArgPair(1<<10, 8)
-    ->ArgPair(1<<10, 64)
-    ->ArgPair(1<<10, 512)
-    ->ArgPair(8<<10, 1)
-    ->ArgPair(8<<10, 8)
-    ->ArgPair(8<<10, 64)
-    ->ArgPair(8<<10, 512);
+    ->Args({1<<10, 1})
+    ->Args({1<<10, 8})
+    ->Args({1<<10, 64})
+    ->Args({1<<10, 512})
+    ->Args({8<<10, 1})
+    ->Args({8<<10, 8})
+    ->Args({8<<10, 64})
+    ->Args({8<<10, 512});
  ```
The preceding code is quite repetitive, and can be replaced with the following
@@ -101,7 +101,7 @@ product of the two specified ranges and
  pair.
```c++
-BENCHMARK(BM_SetInsert)->RangePair(1<<10, 8<<10, 1, 512);
+BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {1, 512}});
  ```
For more complex patterns of inputs, passing a custom function to `Apply` allows
@@ -113,7 +113,7 @@ and a sparse range on the second.
  static void CustomArguments(benchmark::internal::Benchmark* b) {
    for (int i = 0; i <= 10; ++i)
      for (int j = 32; j <= 1024*1024; j *= 8)
-      b->ArgPair(i, j);
+      b->Args({i, j});
  }
  BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
  ```
@@ -125,12 +125,12 @@ running time and the normalized root-mea
```c++
  static void BM_StringCompare(benchmark::State& state) {
-  std::string s1(state.range_x(), '-');
-  std::string s2(state.range_x(), '-');
+  std::string s1(state.range(0), '-');
+  std::string s2(state.range(0), '-');
    while (state.KeepRunning()) {
      benchmark::DoNotOptimize(s1.compare(s2));
    }
-  state.SetComplexityN(state.range_x());
+  state.SetComplexityN(state.range(0));
  }
  BENCHMARK(BM_StringCompare)
      ->RangeMultiplier(2)->Range(1<<10, 1<<18)->Complexity(benchmark::oN);
@@ -162,14 +162,14 @@ template <class Q> int BM_Sequential(ben
    Q q;
    typename Q::value_type v;
    while (state.KeepRunning()) {
-    for (int i = state.range_x(); i--; )
+    for (int i = state.range(0); i--; )
        q.push(v);
-    for (int e = state.range_x(); e--; )
+    for (int e = state.range(0); e--; )
        q.Wait(&v);
    }
    // actually messages, not bytes:
    state.SetBytesProcessed(
-      static_cast<int64_t>(state.iterations())*state.range_x());
+      static_cast<int64_t>(state.iterations())*state.range(0));
  }
  BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
  ```
@@ -206,6 +206,34 @@ BENCHMARK_CAPTURE(BM_takes_args, int_str
  Note that elements of `...args` may refer to global variables. Users should
  avoid modifying global state inside of a benchmark.
+## Using RegisterBenchmark(name, fn, args...)
+
+The `RegisterBenchmark(name, func, args...)` function provides an alternative
+way to create and register benchmarks.
+`RegisterBenchmark(name, func, args...)` creates, registers, and returns a
+pointer to a new benchmark with the specified `name` that invokes
+`func(st, args...)` where `st` is a `benchmark::State` object.
+
+Unlike the `BENCHMARK` registration macros, which can only be used at the 
global
+scope, the `RegisterBenchmark` can be called anywhere. This allows for
+benchmark tests to be registered programmatically.
+
+Additionally `RegisterBenchmark` allows any callable object to be registered
+as a benchmark. Including capturing lambdas and function objects. This
+allows the creation
+
+For Example:
+```c++
+auto BM_test = [](benchmark::State& st, auto Inputs) { /* ... */ };
+
+int main(int argc, char** argv) {
+  for (auto& test_input : { /* ... */ })
+      benchmark::RegisterBenchmark(test_input.name(), BM_test, test_input);
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+}
+```
+
  ### Multithreaded benchmarks
  In a multithreaded test (benchmark invoked by multiple threads 
simultaneously),
  it is guaranteed that none of the threads will start until all have called
@@ -256,7 +284,7 @@ can be reported back with `SetIterationT
```c++
  static void BM_ManualTiming(benchmark::State& state) {
-  int microseconds = state.range_x();
+  int microseconds = state.range(0);
    std::chrono::duration<double, std::micro> sleep_duration {
      static_cast<double>(microseconds)
    };
@@ -427,10 +455,10 @@ static void BM_test(benchmark::State& st
## Output Formats
  The library supports multiple output formats. Use the
-`--benchmark_format=<tabular|json|csv>` flag to set the format type. `tabular` 
is
-the default format.
+`--benchmark_format=<console|json|csv>` flag to set the format type. `console`
+is the default format.
-The Tabular format is intended to be a human readable format. By default
+The Console format is intended to be a human readable format. By default
  the format generates color output. Context is output on stderr and the
  tabular data on stdout. Example tabular output looks like:
  ```
@@ -493,6 +521,12 @@ name,iterations,real_time,cpu_time,bytes
  "BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06,
  ```
+## Output Files
+The library supports writing the output of the benchmark to a file specified
+by `--benchmark_out=<filename>`. The format of the output can be specified
+using `--benchmark_out_format={json|console|csv}`. Specifying
+`--benchmark_out` does not suppress the console output.
+
  ## Debug vs Release
  By default, benchmark builds as a debug library. You will see a warning in 
the output when this is the case. To build it as a release library instead, use:
@@ -507,4 +541,22 @@ cmake -DCMAKE_BUILD_TYPE=Release -DBENCH
  ```
## Linking against the library
-When using gcc, it is necessary to link against pthread to avoid runtime 
exceptions. This is due to how gcc implements std::thread. See [issue 
#67](https://github.com/google/benchmark/issues/67) for more details.
+When using gcc, it is necessary to link against pthread to avoid runtime 
exceptions.
+This is due to how gcc implements std::thread.
+See [issue #67](https://github.com/google/benchmark/issues/67) for more 
details.
+
+## Compiler Support
+
+Google Benchmark uses C++11 when building the library. As such we require
+a modern C++ toolchain, both compiler and standard library.
+
+The following minimum versions are strongly recommended build the library:
+
+* GCC 4.8
+* Clang 3.4
+* Visual Studio 2013
+
+Anything older *may* work.
+
+Note: Using the library and its headers in C++03 is supported. C++11 is only
+required to build the library.

Modified: libcxx/trunk/utils/google-benchmark/include/benchmark/benchmark_api.h
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/include/benchmark/benchmark_api.h?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/include/benchmark/benchmark_api.h 
(original)
+++ libcxx/trunk/utils/google-benchmark/include/benchmark/benchmark_api.h Tue 
Aug  9 13:56:48 2016
@@ -38,12 +38,12 @@ int main(int argc, char** argv) {
  // of memcpy() calls of different lengths:
static void BM_memcpy(benchmark::State& state) {
-  char* src = new char[state.range_x()]; char* dst = new char[state.range_x()];
-  memset(src, 'x', state.range_x());
+  char* src = new char[state.range(0)]; char* dst = new char[state.range(0)];
+  memset(src, 'x', state.range(0));
    while (state.KeepRunning())
-    memcpy(dst, src, state.range_x());
+    memcpy(dst, src, state.range(0));
    state.SetBytesProcessed(int64_t(state.iterations()) *
-                          int64_t(state.range_x()));
+                          int64_t(state.range(0)));
    delete[] src; delete[] dst;
  }
  BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10);
@@ -60,27 +60,27 @@ BENCHMARK(BM_memcpy)->Range(8, 8<<10);
  static void BM_SetInsert(benchmark::State& state) {
    while (state.KeepRunning()) {
      state.PauseTiming();
-    set<int> data = ConstructRandomSet(state.range_x());
+    set<int> data = ConstructRandomSet(state.range(0));
      state.ResumeTiming();
-    for (int j = 0; j < state.range_y(); ++j)
+    for (int j = 0; j < state.range(1); ++j)
        data.insert(RandomNumber());
    }
  }
  BENCHMARK(BM_SetInsert)
-   ->ArgPair(1<<10, 1)
-   ->ArgPair(1<<10, 8)
-   ->ArgPair(1<<10, 64)
-   ->ArgPair(1<<10, 512)
-   ->ArgPair(8<<10, 1)
-   ->ArgPair(8<<10, 8)
-   ->ArgPair(8<<10, 64)
-   ->ArgPair(8<<10, 512);
+   ->Args({1<<10, 1})
+   ->Args({1<<10, 8})
+   ->Args({1<<10, 64})
+   ->Args({1<<10, 512})
+   ->Args({8<<10, 1})
+   ->Args({8<<10, 8})
+   ->Args({8<<10, 64})
+   ->Args({8<<10, 512});
// The preceding code is quite repetitive, and can be replaced with
  // the following short-hand.  The following macro will pick a few
  // appropriate arguments in the product of the two specified ranges
  // and will generate a microbenchmark for each such pair.
-BENCHMARK(BM_SetInsert)->RangePair(1<<10, 8<<10, 1, 512);
+BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {1, 512}});
// For more complex patterns of inputs, passing a custom function
  // to Apply allows programmatic specification of an
@@ -90,7 +90,7 @@ BENCHMARK(BM_SetInsert)->RangePair(1<<10
  static void CustomArguments(benchmark::internal::Benchmark* b) {
    for (int i = 0; i <= 10; ++i)
      for (int j = 32; j <= 1024*1024; j *= 8)
-      b->ArgPair(i, j);
+      b->Args({i, j});
  }
  BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
@@ -101,14 +101,14 @@ template <class Q> int BM_Sequential(ben
    Q q;
    typename Q::value_type v;
    while (state.KeepRunning()) {
-    for (int i = state.range_x(); i--; )
+    for (int i = state.range(0); i--; )
        q.push(v);
-    for (int e = state.range_x(); e--; )
+    for (int e = state.range(0); e--; )
        q.Wait(&v);
    }
    // actually messages, not bytes:
    state.SetBytesProcessed(
-      static_cast<int64_t>(state.iterations())*state.range_x());
+      static_cast<int64_t>(state.iterations())*state.range(0));
  }
  BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
@@ -153,8 +153,15 @@ BENCHMARK(BM_test)->Unit(benchmark::kMil
  #include <stddef.h>
  #include <stdint.h>
+#include <vector>
+
  #include "macros.h"
+#if defined(BENCHMARK_HAS_CXX11)
+#include <type_traits>
+#include <utility>
+#endif
+
  namespace benchmark {
  class BenchmarkReporter;
@@ -165,11 +172,16 @@ void Initialize(int* argc, char** argv);
  // of each matching benchmark. Otherwise run each matching benchmark and
  // report the results.
  //
-// The second overload reports the results using the specified 'reporter'.
+// The second and third overload use the specified 'console_reporter' and
+//  'file_reporter' respectively. 'file_reporter' will write to the file 
specified
+//   by '--benchmark_output'. If '--benchmark_output' is not given the
+//  'file_reporter' is ignored.
  //
  // RETURNS: The number of matching benchmarks.
  size_t RunSpecifiedBenchmarks();
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* reporter);
+size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter);
+size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
+                              BenchmarkReporter* file_reporter);
// If this routine is called, peak memory allocation past this point in the
@@ -258,7 +270,7 @@ typedef double(BigOFunc)(int);
  // benchmark to use.
  class State {
  public:
-  State(size_t max_iters, bool has_x, int x, bool has_y, int y,
+  State(size_t max_iters, const std::vector<int>& ranges,
          int thread_i, int n_threads);
// Returns true if the benchmark should continue through another iteration.
@@ -367,7 +379,7 @@ public:
    }
BENCHMARK_ALWAYS_INLINE
-  size_t complexity_length_n() {
+  int complexity_length_n() {
      return complexity_n_;
    }
@@ -413,17 +425,9 @@ public: // Range arguments for this run. CHECKs if the argument has been set.
    BENCHMARK_ALWAYS_INLINE
-  int range_x() const {
-    assert(has_range_x_);
-    ((void)has_range_x_); // Prevent unused warning.
-    return range_x_;
-  }
-
-  BENCHMARK_ALWAYS_INLINE
-  int range_y() const {
-    assert(has_range_y_);
-    ((void)has_range_y_); // Prevent unused warning.
-    return range_y_;
+  int range(std::size_t pos) const {
+      assert(range_.size() > pos);
+      return range_[pos];
    }
BENCHMARK_ALWAYS_INLINE
@@ -434,11 +438,7 @@ private:
    bool finished_;
    size_t total_iterations_;
- bool has_range_x_;
-  int range_x_;
-
-  bool has_range_y_;
-  int range_y_;
+  std::vector<int> range_;
size_t bytes_processed_;
    size_t items_processed_;
@@ -489,24 +489,22 @@ public:
    // REQUIRES: The function passed to the constructor must accept an arg1.
    Benchmark* Range(int start, int limit);
- // Run this benchmark once for every value in the range [start..limit]
+  // Run this benchmark once for all values in the range [start..limit] with 
specific step
    // REQUIRES: The function passed to the constructor must accept an arg1.
-  Benchmark* DenseRange(int start, int limit);
+  Benchmark* DenseRange(int start, int limit, int step = 1);
- // Run this benchmark once with "x,y" as the extra arguments passed
+  // Run this benchmark once with "args" as the extra arguments passed
    // to the function.
-  // REQUIRES: The function passed to the constructor must accept arg1,arg2.
-  Benchmark* ArgPair(int x, int y);
+  // REQUIRES: The function passed to the constructor must accept arg1, arg2 
...
+  Benchmark* Args(const std::vector<int>& args);
- // Pick a set of values A from the range [lo1..hi1] and a set
-  // of values B from the range [lo2..hi2].  Run the benchmark for
-  // every pair of values in the cartesian product of A and B
-  // (i.e., for all combinations of the values in A and B).
-  // REQUIRES: The function passed to the constructor must accept arg1,arg2.
-  Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2);
+  // Run this benchmark once for a number of values picked from the
+  // ranges [start..limit].  (starts and limits are always picked.)
+  // REQUIRES: The function passed to the constructor must accept arg1, arg2 
...
+  Benchmark* Ranges(const std::vector<std::pair<int, int> >& ranges);
// Pass this benchmark object to *func, which can customize
-  // the benchmark by calling various methods like Arg, ArgPair,
+  // the benchmark by calling various methods like Arg, Args,
    // Threads, etc.
    Benchmark* Apply(void (*func)(Benchmark* benchmark));
@@ -587,6 +585,20 @@ private:
    Benchmark& operator=(Benchmark const&);
  };
+} // namespace internal
+
+// Create and register a benchmark with the specified 'name' that invokes
+// the specified functor 'fn'.
+//
+// RETURNS: A pointer to the registered benchmark.
+internal::Benchmark* RegisterBenchmark(const char* name, internal::Function* 
fn);
+
+#if defined(BENCHMARK_HAS_CXX11)
+template <class Lambda>
+internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn);
+#endif
+
+namespace internal {
  // The class used to hold all Benchmarks created from static function.
  // (ie those created using the BENCHMARK(...) macros.
  class FunctionBenchmark : public Benchmark {
@@ -600,8 +612,57 @@ private:
      Function* func_;
  };
+#ifdef BENCHMARK_HAS_CXX11
+template <class Lambda>
+class LambdaBenchmark : public Benchmark {
+public:
+    virtual void Run(State& st) { lambda_(st); }
+
+private:
+  template <class OLambda>
+  LambdaBenchmark(const char* name, OLambda&& lam)
+      : Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
+
+  LambdaBenchmark(LambdaBenchmark const&) = delete;
+
+private:
+  template <class Lam>
+  friend Benchmark* ::benchmark::RegisterBenchmark(const char*, Lam&&);
+
+  Lambda lambda_;
+};
+#endif
+
  }  // end namespace internal
+inline internal::Benchmark*
+RegisterBenchmark(const char* name, internal::Function* fn) {
+    return internal::RegisterBenchmarkInternal(
+        ::new internal::FunctionBenchmark(name, fn));
+}
+
+#ifdef BENCHMARK_HAS_CXX11
+template <class Lambda>
+internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn) {
+    using BenchType = internal::LambdaBenchmark<typename 
std::decay<Lambda>::type>;
+    return internal::RegisterBenchmarkInternal(
+        ::new BenchType(name, std::forward<Lambda>(fn)));
+}
+#endif
+
+#if defined(BENCHMARK_HAS_CXX11) && \
+     (!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
+template <class Lambda, class ...Args>
+internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn,
+                                       Args&&... args) {
+    return benchmark::RegisterBenchmark(name,
+        [=](benchmark::State& st) { fn(st, args...); });
+}
+#else
+#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
+#endif
+
+
  // The base class for all fixture tests.
  class Fixture: public internal::Benchmark {
  public:
@@ -652,11 +713,11 @@ protected:
// Old-style macros
  #define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
-#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->ArgPair((a1), (a2))
+#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
  #define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
  #define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
  #define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
-  BENCHMARK(n)->RangePair((l1), (h1), (l2), (h2))
+  BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
#if __cplusplus >= 201103L
Modified: libcxx/trunk/utils/google-benchmark/include/benchmark/macros.h
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/include/benchmark/macros.h?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/include/benchmark/macros.h (original)
+++ libcxx/trunk/utils/google-benchmark/include/benchmark/macros.h Tue Aug  9 
13:56:48 2016
@@ -14,7 +14,11 @@
  #ifndef BENCHMARK_MACROS_H_
  #define BENCHMARK_MACROS_H_
-#if __cplusplus < 201103L
+#if __cplusplus >= 201103L
+#define BENCHMARK_HAS_CXX11
+#endif
+
+#ifndef BENCHMARK_HAS_CXX11
  # define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName)  \
      TypeName(const TypeName&);                         \
      TypeName& operator=(const TypeName&)
@@ -53,4 +57,8 @@
  # define BENCHMARK_BUILTIN_EXPECT(x, y) x
  #endif
+#if defined(__GNUC__) && !defined(__clang__)
+#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#endif
+
  #endif  // BENCHMARK_MACROS_H_

Modified: libcxx/trunk/utils/google-benchmark/include/benchmark/reporter.h
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/include/benchmark/reporter.h?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/include/benchmark/reporter.h (original)
+++ libcxx/trunk/utils/google-benchmark/include/benchmark/reporter.h Tue Aug  9 
13:56:48 2016
@@ -156,14 +156,23 @@ class BenchmarkReporter {
  // Simple reporter that outputs benchmark data to the console. This is the
  // default reporter used by RunSpecifiedBenchmarks().
  class ConsoleReporter : public BenchmarkReporter {
- public:
+public:
+  enum OutputOptions {
+    OO_None,
+    OO_Color
+  };
+  explicit ConsoleReporter(OutputOptions color_output = OO_Color)
+      : color_output_(color_output == OO_Color) {}
+
    virtual bool ReportContext(const Context& context);
    virtual void ReportRuns(const std::vector<Run>& reports);
- protected:
+protected:
    virtual void PrintRunData(const Run& report);
-
    size_t name_field_width_;
+
+private:
+  bool color_output_;
  };
class JSONReporter : public BenchmarkReporter {

Modified: libcxx/trunk/utils/google-benchmark/src/benchmark.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/benchmark.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/benchmark.cc (original)
+++ libcxx/trunk/utils/google-benchmark/src/benchmark.cc Tue Aug  9 13:56:48 
2016
@@ -28,6 +28,7 @@
  #include <atomic>
  #include <condition_variable>
  #include <iostream>
+#include <fstream>
  #include <memory>
  #include <thread>
@@ -69,6 +70,12 @@ DEFINE_string(benchmark_format, "console
                "The format to use for console output. Valid values are "
                "'console', 'json', or 'csv'.");
+DEFINE_string(benchmark_out_format, "json",
+              "The format to use for file output. Valid values are "
+              "'console', 'json', or 'csv'.");
+
+DEFINE_string(benchmark_out, "", "The file to write additonal output to");
+
  DEFINE_bool(color_print, true, "Enables colorized logging.");
DEFINE_int32(v, 0, "The level of verbose logging to output");
@@ -306,23 +313,20 @@ namespace internal {
// Information kept per benchmark we may want to run
  struct Benchmark::Instance {
-  std::string    name;
-  Benchmark*     benchmark;
-  bool           has_arg1;
-  int            arg1;
-  bool           has_arg2;
-  int            arg2;
-  TimeUnit       time_unit;
-  int            range_multiplier;
-  bool           use_real_time;
-  bool           use_manual_time;
-  BigO           complexity;
-  BigOFunc*      complexity_lambda;
-  bool           last_benchmark_instance;
-  int            repetitions;
-  double         min_time;
-  int            threads;    // Number of concurrent threads to use
-  bool           multithreaded;  // Is benchmark multi-threaded?
+  std::string      name;
+  Benchmark*       benchmark;
+  std::vector<int> arg;
+  TimeUnit         time_unit;
+  int              range_multiplier;
+  bool             use_real_time;
+  bool             use_manual_time;
+  BigO             complexity;
+  BigOFunc*        complexity_lambda;
+  bool             last_benchmark_instance;
+  int              repetitions;
+  double           min_time;
+  int              threads;    // Number of concurrent threads to use
+  bool             multithreaded;  // Is benchmark multi-threaded?
  };
// Class for managing registered benchmarks. Note that each registered
@@ -354,9 +358,9 @@ public:
    void Arg(int x);
    void Unit(TimeUnit unit);
    void Range(int start, int limit);
-  void DenseRange(int start, int limit);
-  void ArgPair(int start, int limit);
-  void RangePair(int lo1, int hi1, int lo2, int hi2);
+  void DenseRange(int start, int limit, int step = 1);
+  void Args(const std::vector<int>& args);
+  void Ranges(const std::vector<std::pair<int, int>>& ranges);
    void RangeMultiplier(int multiplier);
    void MinTime(double n);
    void Repetitions(int n);
@@ -371,12 +375,13 @@ public:
static void AddRange(std::vector<int>* dst, int lo, int hi, int mult); + int ArgsCnt() const { return args_.empty() ? -1 : static_cast<int>(args_.front().size()); }
+
  private:
    friend class BenchmarkFamilies;
std::string name_;
-  int arg_count_;
-  std::vector< std::pair<int, int> > args_;  // Args for all benchmark runs
+  std::vector< std::vector<int> > args_;  // Args for all benchmark runs
    TimeUnit time_unit_;
    int range_multiplier_;
    double min_time_;
@@ -424,10 +429,10 @@ bool BenchmarkFamilies::FindBenchmarks(
      if (!bench_family) continue;
      BenchmarkImp* family = bench_family->imp_;
- if (family->arg_count_ == -1) {
-      family->arg_count_ = 0;
-      family->args_.emplace_back(-1, -1);
+    if (family->ArgsCnt() == -1) {
+      family->Args({});
      }
+
      for (auto const& args : family->args_) {
        const std::vector<int>* thread_counts =
          (family->thread_counts_.empty()
@@ -438,10 +443,7 @@ bool BenchmarkFamilies::FindBenchmarks(
          Benchmark::Instance instance;
          instance.name = family->name_;
          instance.benchmark = bench_family.get();
-        instance.has_arg1 = family->arg_count_ >= 1;
-        instance.arg1 = args.first;
-        instance.has_arg2 = family->arg_count_ == 2;
-        instance.arg2 = args.second;
+        instance.arg = args;
          instance.time_unit = family->time_unit_;
          instance.range_multiplier = family->range_multiplier_;
          instance.min_time = family->min_time_;
@@ -454,12 +456,10 @@ bool BenchmarkFamilies::FindBenchmarks(
          instance.multithreaded = !(family->thread_counts_.empty());
// Add arguments to instance name
-        if (family->arg_count_ >= 1) {
-          AppendHumanReadable(instance.arg1, &instance.name);
-        }
-        if (family->arg_count_ >= 2) {
-          AppendHumanReadable(instance.arg2, &instance.name);
+        for (auto const& arg : args) {
+          AppendHumanReadable(arg, &instance.name);
          }
+
          if (!IsZero(family->min_time_)) {
            instance.name +=  StringPrintF("/min_time:%0.3f",  
family->min_time_);
          }
@@ -488,7 +488,7 @@ bool BenchmarkFamilies::FindBenchmarks(
  }
BenchmarkImp::BenchmarkImp(const char* name)
-    : name_(name), arg_count_(-1), time_unit_(kNanosecond),
+    : name_(name), time_unit_(kNanosecond),
        range_multiplier_(kRangeMultiplier), min_time_(0.0), repetitions_(0),
        use_real_time_(false), use_manual_time_(false),
        complexity_(oNone) {
@@ -498,9 +498,8 @@ BenchmarkImp::~BenchmarkImp() {
  }
void BenchmarkImp::Arg(int x) {
-  CHECK(arg_count_ == -1 || arg_count_ == 1);
-  arg_count_ = 1;
-  args_.emplace_back(x, -1);
+  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
+  args_.push_back({x});
  }
void BenchmarkImp::Unit(TimeUnit unit) {
@@ -508,42 +507,54 @@ void BenchmarkImp::Unit(TimeUnit unit) {
  }
void BenchmarkImp::Range(int start, int limit) {
-  CHECK(arg_count_ == -1 || arg_count_ == 1);
-  arg_count_ = 1;
+  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
    std::vector<int> arglist;
    AddRange(&arglist, start, limit, range_multiplier_);
for (int i : arglist) {
-    args_.emplace_back(i, -1);
+    args_.push_back({i});
    }
  }
-void BenchmarkImp::DenseRange(int start, int limit) {
-  CHECK(arg_count_ == -1 || arg_count_ == 1);
-  arg_count_ = 1;
+void BenchmarkImp::DenseRange(int start, int limit, int step) {
+  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
    CHECK_GE(start, 0);
    CHECK_LE(start, limit);
-  for (int arg = start; arg <= limit; arg++) {
-    args_.emplace_back(arg, -1);
+  for (int arg = start; arg <= limit; arg+= step) {
+    args_.push_back({arg});
    }
  }
-void BenchmarkImp::ArgPair(int x, int y) {
-  CHECK(arg_count_ == -1 || arg_count_ == 2);
-  arg_count_ = 2;
-  args_.emplace_back(x, y);
+void BenchmarkImp::Args(const std::vector<int>& args)
+{
+  args_.push_back(args);
  }
-void BenchmarkImp::RangePair(int lo1, int hi1, int lo2, int hi2) {
-  CHECK(arg_count_ == -1 || arg_count_ == 2);
-  arg_count_ = 2;
-  std::vector<int> arglist1, arglist2;
-  AddRange(&arglist1, lo1, hi1, range_multiplier_);
-  AddRange(&arglist2, lo2, hi2, range_multiplier_);
+void BenchmarkImp::Ranges(const std::vector<std::pair<int, int>>& ranges) {
+  std::vector<std::vector<int>> arglists(ranges.size());
+  int total = 1;
+  for (std::size_t i = 0; i < ranges.size(); i++) {
+    AddRange(&arglists[i], ranges[i].first, ranges[i].second, 
range_multiplier_);
+    total *= arglists[i].size();
+  }
+
+  std::vector<std::size_t> ctr(total, 0);
- for (int i : arglist1) {
-    for (int j : arglist2) {
-      args_.emplace_back(i, j);
+  for (int i = 0; i < total; i++) {
+    std::vector<int> tmp;
+
+    for (std::size_t j = 0; j < arglists.size(); j++) {
+      tmp.push_back(arglists[j][ctr[j]]);
+    }
+
+    args_.push_back(tmp);
+
+    for (std::size_t j = 0; j < arglists.size(); j++) {
+      if (ctr[j] + 1 < arglists[j].size()) {
+        ++ctr[j];
+        break;
+      }
+      ctr[j] = 0;
      }
    }
  }
@@ -641,6 +652,7 @@ Benchmark::Benchmark(Benchmark const& ot
  }
Benchmark* Benchmark::Arg(int x) {
+  CHECK(imp_->ArgsCnt() == -1 || imp_->ArgsCnt() == 1);
    imp_->Arg(x);
    return this;
  }
@@ -651,22 +663,27 @@ Benchmark* Benchmark::Unit(TimeUnit unit
  }
Benchmark* Benchmark::Range(int start, int limit) {
+  CHECK(imp_->ArgsCnt() == -1 || imp_->ArgsCnt() == 1);
    imp_->Range(start, limit);
    return this;
  }
-Benchmark* Benchmark::DenseRange(int start, int limit) {
-  imp_->DenseRange(start, limit);
+Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges)
+{
+  CHECK(imp_->ArgsCnt() == -1 || imp_->ArgsCnt() == 
static_cast<int>(ranges.size()));
+  imp_->Ranges(ranges);
    return this;
  }
-Benchmark* Benchmark::ArgPair(int x, int y) {
-  imp_->ArgPair(x, y);
+Benchmark* Benchmark::DenseRange(int start, int limit, int step) {
+  CHECK(imp_->ArgsCnt() == -1 || imp_->ArgsCnt() == 1);
+  imp_->DenseRange(start, limit, step);
    return this;
  }
-Benchmark* Benchmark::RangePair(int lo1, int hi1, int lo2, int hi2) {
-  imp_->RangePair(lo1, hi1, lo2, hi2);
+Benchmark* Benchmark::Args(const std::vector<int>& args) {
+  CHECK(imp_->ArgsCnt() == -1 || imp_->ArgsCnt() == 
static_cast<int>(args.size()));
+  imp_->Args(args);
    return this;
  }
@@ -744,7 +761,7 @@ namespace {
  void RunInThread(const benchmark::internal::Benchmark::Instance* b,
                   size_t iters, int thread_id,
                   ThreadStats* total) EXCLUDES(GetBenchmarkLock()) {
-  State st(iters, b->has_arg1, b->arg1, b->has_arg2, b->arg2, thread_id, 
b->threads);
+  State st(iters, b->arg, thread_id, b->threads);
    b->benchmark->Run(st);
    CHECK(st.iterations() == st.max_iterations) <<
      "Benchmark returned before State::KeepRunning() returned false!";
@@ -758,14 +775,13 @@ void RunInThread(const benchmark::intern
    timer_manager->Finalize();
  }
-void RunBenchmark(const benchmark::internal::Benchmark::Instance& b,
-                  BenchmarkReporter* br,
-                  std::vector<BenchmarkReporter::Run>& complexity_reports)
+std::vector<BenchmarkReporter::Run>
+RunBenchmark(const benchmark::internal::Benchmark::Instance& b,
+             std::vector<BenchmarkReporter::Run>* complexity_reports)
    EXCLUDES(GetBenchmarkLock()) {
+   std::vector<BenchmarkReporter::Run> reports; // return value
    size_t iters = 1;
- std::vector<BenchmarkReporter::Run> reports;
-
    std::vector<std::thread> pool;
    if (b.multithreaded)
      pool.resize(b.threads);
@@ -872,7 +888,7 @@ void RunBenchmark(const benchmark::inter
            report.complexity = b.complexity;
            report.complexity_lambda = b.complexity_lambda;
            if(report.complexity != oNone)
-            complexity_reports.push_back(report);
+            complexity_reports->push_back(report);
          }
reports.push_back(report);
@@ -903,27 +919,26 @@ void RunBenchmark(const benchmark::inter
                   additional_run_stats.end());
if((b.complexity != oNone) && b.last_benchmark_instance) {
-    additional_run_stats = ComputeBigO(complexity_reports);
+    additional_run_stats = ComputeBigO(*complexity_reports);
      reports.insert(reports.end(), additional_run_stats.begin(),
                     additional_run_stats.end());
-    complexity_reports.clear();
+    complexity_reports->clear();
    }
- br->ReportRuns(reports);
-
    if (b.multithreaded) {
      for (std::thread& thread : pool)
        thread.join();
    }
+
+  return reports;
  }
} // namespace -State::State(size_t max_iters, bool has_x, int x, bool has_y, int y,
+State::State(size_t max_iters, const std::vector<int>& ranges,
               int thread_i, int n_threads)
      : started_(false), finished_(false), total_iterations_(0),
-      has_range_x_(has_x), range_x_(x),
-      has_range_y_(has_y), range_y_(y),
+      range_(ranges),
        bytes_processed_(0), items_processed_(0),
        complexity_n_(0),
        error_occurred_(false),
@@ -975,8 +990,10 @@ namespace internal {
  namespace {
void RunMatchingBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
-                           BenchmarkReporter* reporter) {
-  CHECK(reporter != nullptr);
+                           BenchmarkReporter* console_reporter,
+                           BenchmarkReporter* file_reporter) {
+  // Note the file_reporter can be null.
+  CHECK(console_reporter != nullptr);
// Determine the width of the name field using a minimum width of 10.
    bool has_repetitions = FLAGS_benchmark_repetitions > 1;
@@ -1000,23 +1017,30 @@ void RunMatchingBenchmarks(const std::ve
    // Keep track of runing times of all instances of current benchmark
    std::vector<BenchmarkReporter::Run> complexity_reports;
- if (reporter->ReportContext(context)) {
+  if (console_reporter->ReportContext(context)
+      && (!file_reporter || file_reporter->ReportContext(context))) {
      for (const auto& benchmark : benchmarks) {
-      RunBenchmark(benchmark, reporter, complexity_reports);
+      std::vector<BenchmarkReporter::Run> reports =
+          RunBenchmark(benchmark, &complexity_reports);
+      console_reporter->ReportRuns(reports);
+      if (file_reporter) file_reporter->ReportRuns(reports);
      }
    }
+  console_reporter->Finalize();
+  if (file_reporter) file_reporter->Finalize();
  }
-std::unique_ptr<BenchmarkReporter> GetDefaultReporter() {
+std::unique_ptr<BenchmarkReporter>
+CreateReporter(std::string const& name, ConsoleReporter::OutputOptions 
allow_color) {
    typedef std::unique_ptr<BenchmarkReporter> PtrType;
-  if (FLAGS_benchmark_format == "console") {
-    return PtrType(new ConsoleReporter);
-  } else if (FLAGS_benchmark_format == "json") {
+  if (name == "console") {
+    return PtrType(new ConsoleReporter(allow_color));
+  } else if (name == "json") {
      return PtrType(new JSONReporter);
-  } else if (FLAGS_benchmark_format == "csv") {
+  } else if (name == "csv") {
      return PtrType(new CSVReporter);
    } else {
-    std::cerr << "Unexpected format: '" << FLAGS_benchmark_format << "'\n";
+    std::cerr << "Unexpected format: '" << name << "'\n";
      std::exit(1);
    }
  }
@@ -1025,10 +1049,17 @@ std::unique_ptr<BenchmarkReporter> GetDe
  } // end namespace internal
size_t RunSpecifiedBenchmarks() {
-  return RunSpecifiedBenchmarks(nullptr);
+  return RunSpecifiedBenchmarks(nullptr, nullptr);
+}
+
+
+size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter) {
+  return RunSpecifiedBenchmarks(console_reporter, nullptr);
  }
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* reporter) {
+
+size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
+                              BenchmarkReporter* file_reporter) {
    std::string spec = FLAGS_benchmark_filter;
    if (spec.empty() || spec == "all")
      spec = ".";  // Regexp that matches all benchmarks
@@ -1041,13 +1072,38 @@ size_t RunSpecifiedBenchmarks(BenchmarkR
      for (auto const& benchmark : benchmarks)
        std::cout <<  benchmark.name << "\n";
    } else {
-    std::unique_ptr<BenchmarkReporter> default_reporter;
-    if (!reporter) {
-      default_reporter = internal::GetDefaultReporter();
-      reporter = default_reporter.get();
+    // Setup the reporters
+    std::ofstream output_file;
+    std::unique_ptr<BenchmarkReporter> default_console_reporter;
+    std::unique_ptr<BenchmarkReporter> default_file_reporter;
+    if (!console_reporter) {
+      auto output_opts = FLAGS_color_print ? ConsoleReporter::OO_Color
+                                           : ConsoleReporter::OO_None;
+      default_console_reporter = internal::CreateReporter(
+          FLAGS_benchmark_format, output_opts);
+      console_reporter = default_console_reporter.get();
      }
-    internal::RunMatchingBenchmarks(benchmarks, reporter);
-    reporter->Finalize();
+    std::string const& fname = FLAGS_benchmark_out;
+    if (fname == "" && file_reporter) {
+      std::cerr << "A custom file reporter was provided but "
+                   "--benchmark_out=<file> was not specified." << std::endl;
+      std::exit(1);
+    }
+    if (fname != "") {
+      output_file.open(fname);
+      if (!output_file.is_open()) {
+        std::cerr << "invalid file name: '" << fname << std::endl;
+        std::exit(1);
+      }
+      if (!file_reporter) {
+        default_file_reporter = internal::CreateReporter(
+            FLAGS_benchmark_out_format, ConsoleReporter::OO_None);
+        file_reporter = default_file_reporter.get();
+      }
+      file_reporter->SetOutputStream(&output_file);
+      file_reporter->SetErrorStream(&output_file);
+    }
+    internal::RunMatchingBenchmarks(benchmarks, console_reporter, 
file_reporter);
    }
    return benchmarks.size();
  }
@@ -1062,6 +1118,8 @@ void PrintUsageAndExit() {
            "          [--benchmark_min_time=<min_time>]\n"
            "          [--benchmark_repetitions=<num_repetitions>]\n"
            "          [--benchmark_format=<console|json|csv>]\n"
+          "          [--benchmark_out=<filename>]\n"
+          "          [--benchmark_out_format=<json|console|csv>]\n"
            "          [--color_print={true|false}]\n"
            "          [--v=<verbosity>]\n");
    exit(0);
@@ -1081,6 +1139,10 @@ void ParseCommandLineFlags(int* argc, ch
                         &FLAGS_benchmark_repetitions) ||
          ParseStringFlag(argv[i], "benchmark_format",
                          &FLAGS_benchmark_format) ||
+        ParseStringFlag(argv[i], "benchmark_out",
+                        &FLAGS_benchmark_out) ||
+        ParseStringFlag(argv[i], "benchmark_out_format",
+                        &FLAGS_benchmark_out_format) ||
          ParseBoolFlag(argv[i], "color_print",
                         &FLAGS_color_print) ||
          ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
@@ -1092,10 +1154,9 @@ void ParseCommandLineFlags(int* argc, ch
        PrintUsageAndExit();
      }
    }
-
-  if (FLAGS_benchmark_format != "console" &&
-      FLAGS_benchmark_format != "json" &&
-      FLAGS_benchmark_format != "csv") {
+  for (auto const* flag : {&FLAGS_benchmark_format,
+                           &FLAGS_benchmark_out_format})
+  if (*flag != "console" && *flag != "json" && *flag != "csv") {
      PrintUsageAndExit();
    }
  }

Modified: libcxx/trunk/utils/google-benchmark/src/colorprint.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/colorprint.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/colorprint.cc (original)
+++ libcxx/trunk/utils/google-benchmark/src/colorprint.cc Tue Aug  9 13:56:48 
2016
@@ -20,7 +20,6 @@
  #include <string>
  #include <memory>
-#include "commandlineflags.h"
  #include "check.h"
  #include "internal_macros.h"
@@ -28,8 +27,6 @@
  #include <Windows.h>
  #endif
-DECLARE_bool(color_print);
-
  namespace benchmark {
  namespace {
  #ifdef BENCHMARK_OS_WINDOWS
@@ -120,14 +117,14 @@ std::string FormatString(const char *msg
  void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
+  ColorPrintf(out, color, fmt, args);
+  va_end(args);
+}
- if (!FLAGS_color_print) {
-    out << FormatString(fmt, args);
-    va_end(args);
-    return;
-  }
-
+void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list 
args) {
  #ifdef BENCHMARK_OS_WINDOWS
+  ((void)out); // suppress unused warning
+
    const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
// Gets the current text color.
@@ -152,7 +149,6 @@ void ColorPrintf(std::ostream& out, LogC
    out << FormatString(fmt, args) << "\033[m";
  #endif
- va_end(args);
  }
} // end namespace benchmark

Modified: libcxx/trunk/utils/google-benchmark/src/colorprint.h
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/colorprint.h?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/colorprint.h (original)
+++ libcxx/trunk/utils/google-benchmark/src/colorprint.h Tue Aug  9 13:56:48 
2016
@@ -20,6 +20,7 @@ enum LogColor {
  std::string FormatString(const char* msg, va_list args);
  std::string FormatString(const char* msg, ...);
+void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list args);
  void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...);
} // end namespace benchmark

Modified: libcxx/trunk/utils/google-benchmark/src/complexity.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/complexity.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/complexity.cc (original)
+++ libcxx/trunk/utils/google-benchmark/src/complexity.cc Tue Aug  9 13:56:48 
2016
@@ -31,9 +31,9 @@ BigOFunc* FittingCurve(BigO complexity)
      case oN:
        return [](int n) -> double { return n; };
      case oNSquared:
-      return [](int n) -> double { return n * n; };
+      return [](int n) -> double { return std::pow(n, 2); };
      case oNCubed:
-      return [](int n) -> double { return n * n * n; };
+      return [](int n) -> double { return std::pow(n, 3); };
      case oLogN:
        return [](int n) { return std::log2(n); };
      case oNLogN:

Modified: libcxx/trunk/utils/google-benchmark/src/console_reporter.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/console_reporter.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/console_reporter.cc (original)
+++ libcxx/trunk/utils/google-benchmark/src/console_reporter.cc Tue Aug  9 
13:56:48 2016
@@ -30,8 +30,6 @@
  #include "string_util.h"
  #include "walltime.h"
-DECLARE_bool(color_print);
-
  namespace benchmark {
bool ConsoleReporter::ReportContext(const Context& context) {
@@ -40,10 +38,10 @@ bool ConsoleReporter::ReportContext(cons
    PrintBasicContext(&GetErrorStream(), context);
#ifdef BENCHMARK_OS_WINDOWS
-  if (FLAGS_color_print && &std::cout != &GetOutputStream()) {
+  if (color_output_ && &std::cout != &GetOutputStream()) {
        GetErrorStream() << "Color printing is only supported for stdout on 
windows."
                            " Disabling color printing\n";
-      FLAGS_color_print = false;
+      color_output_ = false;
    }
  #endif
    std::string str = FormatString("%-*s %13s %13s %10s\n",
@@ -59,18 +57,29 @@ void ConsoleReporter::ReportRuns(const s
      PrintRunData(run);
  }
+static void IgnoreColorPrint(std::ostream& out, LogColor,
+                               const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    out << FormatString(fmt, args);
+    va_end(args);
+}
+
  void ConsoleReporter::PrintRunData(const Run& result) {
+  typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
    auto& Out = GetOutputStream();
-
+  PrinterFn* printer = color_output_ ? (PrinterFn*)ColorPrintf
+                                     : IgnoreColorPrint;
    auto name_color =
        (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN;
-  ColorPrintf(Out, name_color, "%-*s ", name_field_width_,
+  printer(Out, name_color, "%-*s ", name_field_width_,
                result.benchmark_name.c_str());
if (result.error_occurred) {
-    ColorPrintf(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'",
+    printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'",
                  result.error_message.c_str());
-    ColorPrintf(Out, COLOR_DEFAULT, "\n");
+    printer(Out, COLOR_DEFAULT, "\n");
      return;
    }
    // Format bytes per second
@@ -91,34 +100,34 @@ void ConsoleReporter::PrintRunData(const
if (result.report_big_o) {
      std::string big_o = GetBigOString(result.complexity);
-    ColorPrintf(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time,
+    printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time,
                  big_o.c_str(), cpu_time, big_o.c_str());
    } else if (result.report_rms) {
-    ColorPrintf(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100,
+    printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100,
                  cpu_time * 100);
    } else {
      const char* timeLabel = GetTimeUnitString(result.time_unit);
-    ColorPrintf(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, 
timeLabel,
+    printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel,
                  cpu_time, timeLabel);
    }
if (!result.report_big_o && !result.report_rms) {
-    ColorPrintf(Out, COLOR_CYAN, "%10lld", result.iterations);
+    printer(Out, COLOR_CYAN, "%10lld", result.iterations);
    }
if (!rate.empty()) {
-    ColorPrintf(Out, COLOR_DEFAULT, " %*s", 13, rate.c_str());
+    printer(Out, COLOR_DEFAULT, " %*s", 13, rate.c_str());
    }
if (!items.empty()) {
-    ColorPrintf(Out, COLOR_DEFAULT, " %*s", 18, items.c_str());
+    printer(Out, COLOR_DEFAULT, " %*s", 18, items.c_str());
    }
if (!result.report_label.empty()) {
-    ColorPrintf(Out, COLOR_DEFAULT, " %s", result.report_label.c_str());
+    printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str());
    }
- ColorPrintf(Out, COLOR_DEFAULT, "\n");
+  printer(Out, COLOR_DEFAULT, "\n");
  }
} // end namespace benchmark

Modified: libcxx/trunk/utils/google-benchmark/src/cycleclock.h
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/cycleclock.h?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/cycleclock.h (original)
+++ libcxx/trunk/utils/google-benchmark/src/cycleclock.h Tue Aug  9 13:56:48 
2016
@@ -113,11 +113,11 @@ inline BENCHMARK_ALWAYS_INLINE int64_t N
    uint32_t pmuseren;
    uint32_t pmcntenset;
    // Read the user mode perf monitor counter access permissions.
-  asm("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
+  asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
    if (pmuseren & 1) {  // Allows reading perfmon counters for user mode code.
-    asm("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
+    asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
      if (pmcntenset & 0x80000000ul) {  // Is it counting?
-      asm("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
+      asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
        // The counter is set up to count every 64th cycle
        return static_cast<int64_t>(pmccntr) * 64;  // Should optimize to << 6
      }

Modified: libcxx/trunk/utils/google-benchmark/src/sysinfo.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/src/sysinfo.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/src/sysinfo.cc (original)
+++ libcxx/trunk/utils/google-benchmark/src/sysinfo.cc Tue Aug  9 13:56:48 2016
@@ -239,6 +239,7 @@ void InitializeSystemInfo() {
    }
  // TODO: also figure out cpuinfo_num_cpus
+
  #elif defined BENCHMARK_OS_WINDOWS
    // In NT, read MHz from the registry. If we fail to do so or we're in win9x
    // then make a crude estimate.
@@ -251,7 +252,12 @@ void InitializeSystemInfo() {
      cpuinfo_cycles_per_second = static_cast<double>((int64_t)data * 
(int64_t)(1000 * 1000));  // was mhz
    else
      cpuinfo_cycles_per_second = 
static_cast<double>(EstimateCyclesPerSecond());
-// TODO: also figure out cpuinfo_num_cpus
+
+  SYSTEM_INFO sysinfo;
+  // Use memset as opposed to = {} to avoid GCC missing initializer false 
positives.
+  std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
+  GetSystemInfo(&sysinfo);
+  cpuinfo_num_cpus = sysinfo.dwNumberOfProcessors; // number of logical 
processors in the current group
#elif defined BENCHMARK_OS_MACOSX
    // returning "mach time units" per second. the current number of elapsed

Modified: libcxx/trunk/utils/google-benchmark/test/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/CMakeLists.txt?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/CMakeLists.txt (original)
+++ libcxx/trunk/utils/google-benchmark/test/CMakeLists.txt Tue Aug  9 13:56:48 
2016
@@ -45,9 +45,15 @@ add_test(donotoptimize_test donotoptimiz
  compile_benchmark_test(fixture_test)
  add_test(fixture_test fixture_test --benchmark_min_time=0.01)
+compile_benchmark_test(register_benchmark_test)
+add_test(register_benchmark_test register_benchmark_test 
--benchmark_min_time=0.01)
+
  compile_benchmark_test(map_test)
  add_test(map_test map_test --benchmark_min_time=0.01)
+compile_benchmark_test(multiple_ranges_test)
+add_test(multiple_ranges_test multiple_ranges_test --benchmark_min_time=0.01)
+
  compile_benchmark_test(reporter_output_test)
  add_test(reporter_output_test reporter_output_test --benchmark_min_time=0.01)
Modified: libcxx/trunk/utils/google-benchmark/test/basic_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/basic_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/basic_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/basic_test.cc Tue Aug  9 13:56:48 
2016
@@ -14,7 +14,7 @@ BENCHMARK(BM_empty)->ThreadPerCpu();
void BM_spin_empty(benchmark::State& state) {
    while (state.KeepRunning()) {
-    for (int x = 0; x < state.range_x(); ++x) {
+    for (int x = 0; x < state.range(0); ++x) {
        benchmark::DoNotOptimize(x);
      }
    }
@@ -23,11 +23,11 @@ BASIC_BENCHMARK_TEST(BM_spin_empty);
  BASIC_BENCHMARK_TEST(BM_spin_empty)->ThreadPerCpu();
void BM_spin_pause_before(benchmark::State& state) {
-  for (int i = 0; i < state.range_x(); ++i) {
+  for (int i = 0; i < state.range(0); ++i) {
      benchmark::DoNotOptimize(i);
    }
    while(state.KeepRunning()) {
-    for (int i = 0; i < state.range_x(); ++i) {
+    for (int i = 0; i < state.range(0); ++i) {
        benchmark::DoNotOptimize(i);
      }
    }
@@ -39,11 +39,11 @@ BASIC_BENCHMARK_TEST(BM_spin_pause_befor
  void BM_spin_pause_during(benchmark::State& state) {
    while(state.KeepRunning()) {
      state.PauseTiming();
-    for (int i = 0; i < state.range_x(); ++i) {
+    for (int i = 0; i < state.range(0); ++i) {
        benchmark::DoNotOptimize(i);
      }
      state.ResumeTiming();
-    for (int i = 0; i < state.range_x(); ++i) {
+    for (int i = 0; i < state.range(0); ++i) {
        benchmark::DoNotOptimize(i);
      }
    }
@@ -64,11 +64,11 @@ BENCHMARK(BM_pause_during)->UseRealTime(
void BM_spin_pause_after(benchmark::State& state) {
    while(state.KeepRunning()) {
-    for (int i = 0; i < state.range_x(); ++i) {
+    for (int i = 0; i < state.range(0); ++i) {
        benchmark::DoNotOptimize(i);
      }
    }
-  for (int i = 0; i < state.range_x(); ++i) {
+  for (int i = 0; i < state.range(0); ++i) {
      benchmark::DoNotOptimize(i);
    }
  }
@@ -77,15 +77,15 @@ BASIC_BENCHMARK_TEST(BM_spin_pause_after
void BM_spin_pause_before_and_after(benchmark::State& state) {
-  for (int i = 0; i < state.range_x(); ++i) {
+  for (int i = 0; i < state.range(0); ++i) {
      benchmark::DoNotOptimize(i);
    }
    while(state.KeepRunning()) {
-    for (int i = 0; i < state.range_x(); ++i) {
+    for (int i = 0; i < state.range(0); ++i) {
        benchmark::DoNotOptimize(i);
      }
    }
-  for (int i = 0; i < state.range_x(); ++i) {
+  for (int i = 0; i < state.range(0); ++i) {
      benchmark::DoNotOptimize(i);
    }
  }

Modified: libcxx/trunk/utils/google-benchmark/test/benchmark_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/benchmark_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/benchmark_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/benchmark_test.cc Tue Aug  9 
13:56:48 2016
@@ -67,7 +67,7 @@ BENCHMARK(BM_Factorial)->UseRealTime();
  static void BM_CalculatePiRange(benchmark::State& state) {
    double pi = 0.0;
    while (state.KeepRunning())
-    pi = CalculatePi(state.range_x());
+    pi = CalculatePi(state.range(0));
    std::stringstream ss;
    ss << pi;
    state.SetLabel(ss.str());
@@ -87,25 +87,25 @@ BENCHMARK(BM_CalculatePi)->ThreadPerCpu(
  static void BM_SetInsert(benchmark::State& state) {
    while (state.KeepRunning()) {
      state.PauseTiming();
-    std::set<int> data = ConstructRandomSet(state.range_x());
+    std::set<int> data = ConstructRandomSet(state.range(0));
      state.ResumeTiming();
-    for (int j = 0; j < state.range_y(); ++j)
+    for (int j = 0; j < state.range(1); ++j)
        data.insert(rand());
    }
-  state.SetItemsProcessed(state.iterations() * state.range_y());
-  state.SetBytesProcessed(state.iterations() * state.range_y() * sizeof(int));
+  state.SetItemsProcessed(state.iterations() * state.range(1));
+  state.SetBytesProcessed(state.iterations() * state.range(1) * sizeof(int));
  }
-BENCHMARK(BM_SetInsert)->RangePair(1<<10,8<<10, 1,10);
+BENCHMARK(BM_SetInsert)->Ranges({{1<<10,8<<10}, {1,10}});
template<typename Container, typename ValueType = typename Container::value_type>
  static void BM_Sequential(benchmark::State& state) {
    ValueType v = 42;
    while (state.KeepRunning()) {
      Container c;
-    for (int i = state.range_x(); --i; )
+    for (int i = state.range(0); --i; )
        c.push_back(v);
    }
-  const size_t items_processed = state.iterations() * state.range_x();
+  const size_t items_processed = state.iterations() * state.range(0);
    state.SetItemsProcessed(items_processed);
    state.SetBytesProcessed(items_processed * sizeof(v));
  }
@@ -117,8 +117,8 @@ BENCHMARK_TEMPLATE(BM_Sequential, std::v
  #endif
static void BM_StringCompare(benchmark::State& state) {
-  std::string s1(state.range_x(), '-');
-  std::string s2(state.range_x(), '-');
+  std::string s1(state.range(0), '-');
+  std::string s2(state.range(0), '-');
    while (state.KeepRunning())
      benchmark::DoNotOptimize(s1.compare(s2));
  }
@@ -147,14 +147,14 @@ BENCHMARK(BM_SetupTeardown)->ThreadPerCp
  static void BM_LongTest(benchmark::State& state) {
    double tracker = 0.0;
    while (state.KeepRunning()) {
-    for (int i = 0; i < state.range_x(); ++i)
+    for (int i = 0; i < state.range(0); ++i)
        benchmark::DoNotOptimize(tracker += i);
    }
  }
  BENCHMARK(BM_LongTest)->Range(1<<16,1<<28);
static void BM_ParallelMemset(benchmark::State& state) {
-  int size = state.range_x() / sizeof(int);
+  int size = state.range(0) / sizeof(int);
    int thread_size = size / state.threads;
    int from = thread_size * state.thread_index;
    int to = from + thread_size;
@@ -179,7 +179,7 @@ BENCHMARK(BM_ParallelMemset)->Arg(10 <<
static void BM_ManualTiming(benchmark::State& state) {
    size_t slept_for = 0;
-  int microseconds = state.range_x();
+  int microseconds = state.range(0);
    std::chrono::duration<double, std::micro> sleep_duration {
      static_cast<double>(microseconds)
    };

Modified: libcxx/trunk/utils/google-benchmark/test/complexity_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/complexity_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/complexity_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/complexity_test.cc Tue Aug  9 
13:56:48 2016
@@ -36,18 +36,27 @@ struct TestCase {
      CHECK(err_str.empty()) << "Could not construct regex \"" << regex << "\""
                             << " got Error: " << err_str;
+ std::string near = "<EOF>";
      std::string line;
+    bool first = true;
      while (remaining_output.eof() == false) {
          CHECK(remaining_output.good());
          std::getline(remaining_output, line);
+        // Keep the first line as context.
+        if (first) {
+            near = line;
+            first = false;
+        }
          if (r.Match(line)) return;
          CHECK(match_rule != MR_Next) << "Expected line \"" << line
-                                     << "\" to match regex \"" << regex << 
"\"";
+                                     << "\" to match regex \"" << regex << "\""
+                                     << "\nstarted matching at line: \"" << near << 
"\"";
      }
CHECK(remaining_output.eof() == false)
          << "End of output reached before match for regex \"" << regex
-        << "\" was found";
+        << "\" was found"
+        << "\nstarted matching at line: \"" << near << "\"";
    }
  };
@@ -112,7 +121,7 @@ std::string join(First f, Args&&... args
      return std::string(std::move(f)) + "[ ]+" + 
join(std::forward<Args>(args)...);
  }
-std::string dec_re = "[0-9]+\\.[0-9]+";
+std::string dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
#define ADD_COMPLEXITY_CASES(...) \
      int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__)
@@ -138,7 +147,7 @@ int AddComplexityTest(std::vector<TestCa
    });
    AddCases(csv_out, {
      {"^\"" + big_o_test_name + "\",," + dec_re + "," + dec_re + "," + big_o + 
",,,,,$"},
-    {"^\"" + rms_test_name + "\",," + dec_re + "," + dec_re + ",,,,,,$"}
+    {"^\"" + rms_test_name + "\",," + dec_re + "," + dec_re + ",,,,,,$", 
MR_Next}
    });
    return 0;
  }
@@ -151,12 +160,15 @@ int AddComplexityTest(std::vector<TestCa
void BM_Complexity_O1(benchmark::State& state) {
    while (state.KeepRunning()) {
+      for (int i=0; i < 1024; ++i) {
+          benchmark::DoNotOptimize(&i);
+      }
    }
-  state.SetComplexityN(state.range_x());
+  state.SetComplexityN(state.range(0));
  }
  BENCHMARK(BM_Complexity_O1) -> Range(1, 1<<18) -> Complexity(benchmark::o1);
-BENCHMARK(BM_Complexity_O1) -> Range(1, 1<<18) -> Complexity([](int){return 
1.0; });
  BENCHMARK(BM_Complexity_O1) -> Range(1, 1<<18) -> Complexity();
+BENCHMARK(BM_Complexity_O1) -> Range(1, 1<<18) -> Complexity([](int){return 
1.0; });
const char* big_o_1_test_name = "BM_Complexity_O1_BigO";
  const char* rms_o_1_test_name = "BM_Complexity_O1_RMS";
@@ -167,6 +179,10 @@ const char* lambda_big_o_1 = "f\\(N\\)";
  ADD_COMPLEXITY_CASES(&ConsoleOutputTests, &JSONOutputTests, &CSVOutputTests,
                       big_o_1_test_name, rms_o_1_test_name, enum_auto_big_o_1);
+// Add auto enum tests
+ADD_COMPLEXITY_CASES(&ConsoleOutputTests, &JSONOutputTests, &CSVOutputTests,
+                     big_o_1_test_name, rms_o_1_test_name, enum_auto_big_o_1);
+
  // Add lambda tests
  ADD_COMPLEXITY_CASES(&ConsoleOutputTests, &JSONOutputTests, &CSVOutputTests,
                       big_o_1_test_name, rms_o_1_test_name, lambda_big_o_1);
@@ -185,12 +201,12 @@ std::vector<int> ConstructRandomVector(i
  }
void BM_Complexity_O_N(benchmark::State& state) {
-  auto v = ConstructRandomVector(state.range_x());
-  const int item_not_in_vector = state.range_x()*2; // Test worst case 
scenario (item not in vector)
+  auto v = ConstructRandomVector(state.range(0));
+  const int item_not_in_vector = state.range(0)*2; // Test worst case scenario 
(item not in vector)
    while (state.KeepRunning()) {
        benchmark::DoNotOptimize(std::find(v.begin(), v.end(), 
item_not_in_vector));
    }
-  state.SetComplexityN(state.range_x());
+  state.SetComplexityN(state.range(0));
  }
  BENCHMARK(BM_Complexity_O_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> 
Complexity(benchmark::oN);
  BENCHMARK(BM_Complexity_O_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> 
Complexity([](int n) -> double{return n; });
@@ -214,11 +230,11 @@ ADD_COMPLEXITY_CASES(&ConsoleOutputTests
  // ========================================================================= 
//
static void BM_Complexity_O_N_log_N(benchmark::State& state) {
-  auto v = ConstructRandomVector(state.range_x());
+  auto v = ConstructRandomVector(state.range(0));
    while (state.KeepRunning()) {
        std::sort(v.begin(), v.end());
    }
-  state.SetComplexityN(state.range_x());
+  state.SetComplexityN(state.range(0));
  }
  BENCHMARK(BM_Complexity_O_N_log_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) 
-> Complexity(benchmark::oNLogN);
  BENCHMARK(BM_Complexity_O_N_log_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) 
-> Complexity([](int n) {return n * std::log2(n); });
@@ -244,14 +260,8 @@ ADD_COMPLEXITY_CASES(&ConsoleOutputTests
int main(int argc, char* argv[]) {
-  // Add --color_print=false to argv since we don't want to match color codes.
-  char new_arg[64];
-  char* new_argv[64];
-  std::copy(argv, argv + argc, new_argv);
-  new_argv[argc++] = std::strcpy(new_arg, "--color_print=false");
-  benchmark::Initialize(&argc, new_argv);
-
-  benchmark::ConsoleReporter CR;
+  benchmark::Initialize(&argc, argv);
+  benchmark::ConsoleReporter CR(benchmark::ConsoleReporter::OO_None);
    benchmark::JSONReporter JR;
    benchmark::CSVReporter CSVR;
    struct ReporterTest {

Modified: libcxx/trunk/utils/google-benchmark/test/fixture_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/fixture_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/fixture_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/fixture_test.cc Tue Aug  9 
13:56:48 2016
@@ -44,7 +44,7 @@ BENCHMARK_DEFINE_F(MyFixture, Bar)(bench
      assert(data.get() != nullptr);
      assert(*data == 42);
    }
-  st.SetItemsProcessed(st.range_x());
+  st.SetItemsProcessed(st.range(0));
  }
  BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42);
  BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42)->ThreadPerCpu();

Modified: libcxx/trunk/utils/google-benchmark/test/map_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/map_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/map_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/map_test.cc Tue Aug  9 13:56:48 
2016
@@ -17,7 +17,7 @@ std::map<int, int> ConstructRandomMap(in
// Basic version.
  static void BM_MapLookup(benchmark::State& state) {
-  const int size = state.range_x();
+  const int size = state.range(0);
    while (state.KeepRunning()) {
      state.PauseTiming();
      std::map<int, int> m = ConstructRandomMap(size);
@@ -34,7 +34,7 @@ BENCHMARK(BM_MapLookup)->Range(1 << 3, 1
  class MapFixture : public ::benchmark::Fixture {
   public:
    void SetUp(const ::benchmark::State& st) {
-    m = ConstructRandomMap(st.range_x());
+    m = ConstructRandomMap(st.range(0));
    }
void TearDown(const ::benchmark::State&) {
@@ -45,7 +45,7 @@ class MapFixture : public ::benchmark::F
  };
BENCHMARK_DEFINE_F(MapFixture, Lookup)(benchmark::State& state) {
-  const int size = state.range_x();
+  const int size = state.range(0);
    while (state.KeepRunning()) {
      for (int i = 0; i < size; ++i) {
        benchmark::DoNotOptimize(m.find(rand() % size));

Added: libcxx/trunk/utils/google-benchmark/test/multiple_ranges_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/multiple_ranges_test.cc?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/multiple_ranges_test.cc (added)
+++ libcxx/trunk/utils/google-benchmark/test/multiple_ranges_test.cc Tue Aug  9 
13:56:48 2016
@@ -0,0 +1,46 @@
+#include "benchmark/benchmark.h"
+
+#include <set>
+#include <cassert>
+
+class MultipleRangesFixture : public ::benchmark::Fixture {
+ public:
+  MultipleRangesFixture()
+      : expectedValues({
+        {1, 3, 5}, {1, 3, 8}, {1, 3, 15}, {2, 3, 5}, {2, 3, 8}, {2, 3, 15},
+        {1, 4, 5}, {1, 4, 8}, {1, 4, 15}, {2, 4, 5}, {2, 4, 8}, {2, 4, 15},
+        {1, 7, 5}, {1, 7, 8}, {1, 7, 15}, {2, 7, 5}, {2, 7, 8}, {2, 7, 15},
+        {7, 6, 3}
+      })
+  {
+  }
+
+  void SetUp(const ::benchmark::State& state) {
+    std::vector<int> ranges = {state.range(0), state.range(1), state.range(2)};
+
+    assert(expectedValues.find(ranges) != expectedValues.end());
+
+    actualValues.insert(ranges);
+  }
+
+  virtual ~MultipleRangesFixture() {
+    assert(actualValues.size() == expectedValues.size());
+  }
+
+  std::set<std::vector<int>> expectedValues;
+  std::set<std::vector<int>> actualValues;
+};
+
+
+BENCHMARK_DEFINE_F(MultipleRangesFixture, Empty)(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    int product = state.range(0) * state.range(1) * state.range(2);
+    for (int x = 0; x < product; x++) {
+      benchmark::DoNotOptimize(x);
+    }
+  }
+}
+
+BENCHMARK_REGISTER_F(MultipleRangesFixture, 
Empty)->RangeMultiplier(2)->Ranges({{1, 2}, {3, 7}, {5, 15}})->Args({7, 6, 3});
+
+BENCHMARK_MAIN()

Modified: libcxx/trunk/utils/google-benchmark/test/options_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/options_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/options_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/options_test.cc Tue Aug  9 
13:56:48 2016
@@ -9,7 +9,7 @@ void BM_basic(benchmark::State& state) {
  }
void BM_basic_slow(benchmark::State& state) {
-  std::chrono::milliseconds sleep_duration(state.range_x());
+  std::chrono::milliseconds sleep_duration(state.range(0));
    while (state.KeepRunning()) {
      std::this_thread::sleep_for(
        std::chrono::duration_cast<std::chrono::nanoseconds>(sleep_duration)
@@ -25,8 +25,8 @@ BENCHMARK(BM_basic_slow)->Arg(1000)->Uni
  BENCHMARK(BM_basic)->Range(1, 8);
  BENCHMARK(BM_basic)->RangeMultiplier(2)->Range(1, 8);
  BENCHMARK(BM_basic)->DenseRange(10, 15);
-BENCHMARK(BM_basic)->ArgPair(42, 42);
-BENCHMARK(BM_basic)->RangePair(64, 512, 64, 512);
+BENCHMARK(BM_basic)->Args({42, 42});
+BENCHMARK(BM_basic)->Ranges({{64, 512}, {64, 512}});
  BENCHMARK(BM_basic)->MinTime(0.7);
  BENCHMARK(BM_basic)->UseRealTime();
  BENCHMARK(BM_basic)->ThreadRange(2, 4);

Added: libcxx/trunk/utils/google-benchmark/test/register_benchmark_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/register_benchmark_test.cc?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/register_benchmark_test.cc (added)
+++ libcxx/trunk/utils/google-benchmark/test/register_benchmark_test.cc Tue Aug 
 9 13:56:48 2016
@@ -0,0 +1,149 @@
+
+#undef NDEBUG
+#include "benchmark/benchmark.h"
+#include "../src/check.h" // NOTE: check.h is for internal use only!
+#include <cassert>
+#include <vector>
+
+namespace {
+
+class TestReporter : public benchmark::ConsoleReporter {
+public:
+  virtual void ReportRuns(const std::vector<Run>& report) {
+    all_runs_.insert(all_runs_.end(), begin(report), end(report));
+    ConsoleReporter::ReportRuns(report);
+  }
+
+  std::vector<Run> all_runs_;
+};
+
+struct TestCase {
+  std::string name;
+  const char* label;
+  TestCase(const char* xname) : name(xname), label(nullptr) {}
+  TestCase(const char* xname, const char* xlabel)
+    : name(xname), label(xlabel) {}
+
+  typedef benchmark::BenchmarkReporter::Run Run;
+
+  void CheckRun(Run const& run) const {
+    CHECK(name == run.benchmark_name) << "expected " << name
+                                      << " got " << run.benchmark_name;
+    if (label) {
+      CHECK(run.report_label == label) << "expected " << label
+                                       << " got " << run.report_label;
+    } else {
+      CHECK(run.report_label == "");
+    }
+  }
+};
+
+std::vector<TestCase> ExpectedResults;
+
+int AddCases(std::initializer_list<TestCase> const& v) {
+  for (auto N : v) {
+    ExpectedResults.push_back(N);
+  }
+  return 0;
+}
+
+#define CONCAT(x, y) CONCAT2(x, y)
+#define CONCAT2(x, y) x##y
+#define ADD_CASES(...) \
+int CONCAT(dummy, __LINE__) = AddCases({__VA_ARGS__})
+
+}  // end namespace
+
+typedef benchmark::internal::Benchmark* ReturnVal;
+
+//----------------------------------------------------------------------------//
+// Test RegisterBenchmark with no additional arguments
+//----------------------------------------------------------------------------//
+void BM_function(benchmark::State& state) { while (state.KeepRunning()) {} }
+BENCHMARK(BM_function);
+ReturnVal dummy = benchmark::RegisterBenchmark(
+    "BM_function_manual_registration",
+     BM_function);
+ADD_CASES({"BM_function"}, {"BM_function_manual_registration"});
+
+//----------------------------------------------------------------------------//
+// Test RegisterBenchmark with additional arguments
+// Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they
+//       reject the variadic pack expansion of lambda captures.
+//----------------------------------------------------------------------------//
+#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
+
+void BM_extra_args(benchmark::State& st, const char* label) {
+  while (st.KeepRunning()) {}
+  st.SetLabel(label);
+}
+int RegisterFromFunction() {
+  std::pair<const char*, const char*> cases[] = {
+      {"test1", "One"},
+      {"test2", "Two"},
+      {"test3", "Three"}
+  };
+  for (auto& c : cases)
+    benchmark::RegisterBenchmark(c.first, &BM_extra_args, c.second);
+  return 0;
+}
+int dummy2 = RegisterFromFunction();
+ADD_CASES(
+  {"test1", "One"},
+  {"test2", "Two"},
+  {"test3", "Three"}
+);
+
+#endif // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
+
+//----------------------------------------------------------------------------//
+// Test RegisterBenchmark with different callable types
+//----------------------------------------------------------------------------//
+
+struct CustomFixture {
+  void operator()(benchmark::State& st) {
+    while (st.KeepRunning()) {}
+  }
+};
+
+void TestRegistrationAtRuntime() {
+#ifdef BENCHMARK_HAS_CXX11
+  {
+    CustomFixture fx;
+    benchmark::RegisterBenchmark("custom_fixture", fx);
+    AddCases({"custom_fixture"});
+  }
+#endif
+#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
+  {
+    int x = 42;
+    auto capturing_lam = [=](benchmark::State& st) {
+      while (st.KeepRunning()) {}
+      st.SetLabel(std::to_string(x));
+    };
+    benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam);
+    AddCases({{"lambda_benchmark", "42"}});
+  }
+#endif
+}
+
+int main(int argc, char* argv[]) {
+  TestRegistrationAtRuntime();
+
+  benchmark::Initialize(&argc, argv);
+
+  TestReporter test_reporter;
+  benchmark::RunSpecifiedBenchmarks(&test_reporter);
+
+  typedef benchmark::BenchmarkReporter::Run Run;
+  auto EB = ExpectedResults.begin();
+
+  for (Run const& run : test_reporter.all_runs_) {
+    assert(EB != ExpectedResults.end());
+    EB->CheckRun(run);
+    ++EB;
+  }
+  assert(EB == ExpectedResults.end());
+
+  return 0;
+}

Modified: libcxx/trunk/utils/google-benchmark/test/reporter_output_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/reporter_output_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/reporter_output_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/reporter_output_test.cc Tue Aug  9 
13:56:48 2016
@@ -114,7 +114,9 @@ std::string join(First f, Args&&... args
      return std::string(std::move(f)) + "[ ]+" + 
join(std::forward<Args>(args)...);
  }
-std::string dec_re = "[0-9]+\\.[0-9]+";
+
+
+std::string dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
} // end namespace @@ -185,7 +187,7 @@ ADD_CASES(&CSVOutputTests, {
  void BM_Complexity_O1(benchmark::State& state) {
    while (state.KeepRunning()) {
    }
-  state.SetComplexityN(state.range_x());
+  state.SetComplexityN(state.range(0));
  }
  BENCHMARK(BM_Complexity_O1)->Range(1, 1<<18)->Complexity(benchmark::o1);
@@ -203,14 +205,8 @@ ADD_CASES(&ConsoleOutputTests, { int main(int argc, char* argv[]) {
-  // Add --color_print=false to argv since we don't want to match color codes.
-  char new_arg[64];
-  char* new_argv[64];
-  std::copy(argv, argv + argc, new_argv);
-  new_argv[argc++] = std::strcpy(new_arg, "--color_print=false");
-  benchmark::Initialize(&argc, new_argv);
-
-  benchmark::ConsoleReporter CR;
+  benchmark::Initialize(&argc, argv);
+  benchmark::ConsoleReporter CR(benchmark::ConsoleReporter::OO_None);
    benchmark::JSONReporter JR;
    benchmark::CSVReporter CSVR;
    struct ReporterTest {

Modified: libcxx/trunk/utils/google-benchmark/test/skip_with_error_test.cc
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/test/skip_with_error_test.cc?rev=278147&r1=278146&r2=278147&view=diff
==============================================================================
--- libcxx/trunk/utils/google-benchmark/test/skip_with_error_test.cc (original)
+++ libcxx/trunk/utils/google-benchmark/test/skip_with_error_test.cc Tue Aug  9 
13:56:48 2016
@@ -74,7 +74,7 @@ ADD_CASES("BM_error_before_running",
  void BM_error_during_running(benchmark::State& state) {
    int first_iter = true;
    while (state.KeepRunning()) {
-    if (state.range_x() == 1 && state.thread_index <= (state.threads / 2)) {
+    if (state.range(0) == 1 && state.thread_index <= (state.threads / 2)) {
        assert(first_iter);
        first_iter = false;
        state.SkipWithError("error message");
@@ -116,7 +116,7 @@ ADD_CASES(
  void BM_error_while_paused(benchmark::State& state) {
    bool first_iter = true;
    while (state.KeepRunning()) {
-    if (state.range_x() == 1 && state.thread_index <= (state.threads / 2)) {
+    if (state.range(0) == 1 && state.thread_index <= (state.threads / 2)) {
        assert(first_iter);
        first_iter = false;
        state.PauseTiming();

Added: libcxx/trunk/utils/google-benchmark/tools/compare_bench.py
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/tools/compare_bench.py?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/tools/compare_bench.py (added)
+++ libcxx/trunk/utils/google-benchmark/tools/compare_bench.py Tue Aug  9 
13:56:48 2016
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+"""
+compare_bench.py - Compare two benchmarks or their results and report the
+                   difference.
+"""
+import sys
+import gbench
+from gbench import util, report
+
+def main():
+    # Parse the command line flags
+    def usage():
+        print('compare_bench.py <test1> <test2> [benchmark options]...')
+        exit(1)
+    if '--help' in sys.argv or len(sys.argv) < 3:
+        usage()
+    tests = sys.argv[1:3]
+    bench_opts = sys.argv[3:]
+    bench_opts = list(bench_opts)
+    # Run the benchmarks and report the results
+    json1 = gbench.util.run_or_load_benchmark(tests[0], bench_opts)
+    json2 = gbench.util.run_or_load_benchmark(tests[1], bench_opts)
+    output_lines = gbench.report.generate_difference_report(json1, json2)
+    print 'Comparing %s to %s' % (tests[0], tests[1])
+    for ln in output_lines:
+        print(ln)
+
+
+if __name__ == '__main__':
+    main()

Added: libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json 
(added)
+++ libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json Tue 
Aug  9 13:56:48 2016
@@ -0,0 +1,46 @@
+{
+  "context": {
+    "date": "2016-08-02 17:44:46",
+    "num_cpus": 4,
+    "mhz_per_cpu": 4228,
+    "cpu_scaling_enabled": false,
+    "library_build_type": "release"
+  },
+  "benchmarks": [
+    {
+      "name": "BM_SameTimes",
+      "iterations": 1000,
+      "real_time": 10,
+      "cpu_time": 10,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_2xFaster",
+      "iterations": 1000,
+      "real_time": 50,
+      "cpu_time": 50,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_2xSlower",
+      "iterations": 1000,
+      "real_time": 50,
+      "cpu_time": 50,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_10PercentFaster",
+      "iterations": 1000,
+      "real_time": 100,
+      "cpu_time": 100,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_10PercentSlower",
+      "iterations": 1000,
+      "real_time": 100,
+      "cpu_time": 100,
+      "time_unit": "ns"
+    }
+  ]
+}
\ No newline at end of file

Added: libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json 
(added)
+++ libcxx/trunk/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json Tue 
Aug  9 13:56:48 2016
@@ -0,0 +1,46 @@
+{
+  "context": {
+    "date": "2016-08-02 17:44:46",
+    "num_cpus": 4,
+    "mhz_per_cpu": 4228,
+    "cpu_scaling_enabled": false,
+    "library_build_type": "release"
+  },
+  "benchmarks": [
+    {
+      "name": "BM_SameTimes",
+      "iterations": 1000,
+      "real_time": 10,
+      "cpu_time": 10,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_2xFaster",
+      "iterations": 1000,
+      "real_time": 25,
+      "cpu_time": 25,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_2xSlower",
+      "iterations": 20833333,
+      "real_time": 100,
+      "cpu_time": 100,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_10PercentFaster",
+      "iterations": 1000,
+      "real_time": 90,
+      "cpu_time": 90,
+      "time_unit": "ns"
+    },
+    {
+      "name": "BM_10PercentSlower",
+      "iterations": 1000,
+      "real_time": 110,
+      "cpu_time": 110,
+      "time_unit": "ns"
+    }
+  ]
+}
\ No newline at end of file

Added: libcxx/trunk/utils/google-benchmark/tools/gbench/__init__.py
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/tools/gbench/__init__.py?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/tools/gbench/__init__.py (added)
+++ libcxx/trunk/utils/google-benchmark/tools/gbench/__init__.py Tue Aug  9 
13:56:48 2016
@@ -0,0 +1,8 @@
+"""Google Benchmark tooling"""
+
+__author__ = 'Eric Fiselier'
+__email__ = 'e...@efcs.ca'
+__versioninfo__ = (0, 5, 0)
+__version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev'
+
+__all__ = []

Added: libcxx/trunk/utils/google-benchmark/tools/gbench/report.py
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/tools/gbench/report.py?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/tools/gbench/report.py (added)
+++ libcxx/trunk/utils/google-benchmark/tools/gbench/report.py Tue Aug  9 
13:56:48 2016
@@ -0,0 +1,136 @@
+"""report.py - Utilities for reporting statistics about benchmark results
+"""
+import os
+
+class BenchmarkColor(object):
+    def __init__(self, name, code):
+        self.name = name
+        self.code = code
+
+    def __repr__(self):
+        return '%s%r' % (self.__class__.__name__,
+                         (self.name, self.code))
+
+    def __format__(self, format):
+        return self.code
+
+# Benchmark Colors Enumeration
+BC_NONE = BenchmarkColor('NONE', '')
+BC_MAGENTA = BenchmarkColor('MAGENTA', '\033[95m')
+BC_CYAN = BenchmarkColor('CYAN', '\033[96m')
+BC_OKBLUE = BenchmarkColor('OKBLUE', '\033[94m')
+BC_HEADER = BenchmarkColor('HEADER', '\033[92m')
+BC_WARNING = BenchmarkColor('WARNING', '\033[93m')
+BC_WHITE = BenchmarkColor('WHITE', '\033[97m')
+BC_FAIL = BenchmarkColor('FAIL', '\033[91m')
+BC_ENDC = BenchmarkColor('ENDC', '\033[0m')
+BC_BOLD = BenchmarkColor('BOLD', '\033[1m')
+BC_UNDERLINE = BenchmarkColor('UNDERLINE', '\033[4m')
+
+def color_format(use_color, fmt_str, *args, **kwargs):
+    """
+    Return the result of 'fmt_str.format(*args, **kwargs)' after transforming
+    'args' and 'kwargs' according to the value of 'use_color'. If 'use_color'
+    is False then all color codes in 'args' and 'kwargs' are replaced with
+    the empty string.
+    """
+    assert use_color is True or use_color is False
+    if not use_color:
+        args = [arg if not isinstance(arg, BenchmarkColor) else BC_NONE
+                for arg in args]
+        kwargs = {key: arg if not isinstance(arg, BenchmarkColor) else BC_NONE
+                  for key, arg in kwargs.items()}
+    return fmt_str.format(*args, **kwargs)
+
+
+def find_longest_name(benchmark_list):
+    """
+    Return the length of the longest benchmark name in a given list of
+    benchmark JSON objects
+    """
+    longest_name = 1
+    for bc in benchmark_list:
+        if len(bc['name']) > longest_name:
+            longest_name = len(bc['name'])
+    return longest_name
+
+
+def calculate_change(old_val, new_val):
+    """
+    Return a float representing the decimal change between old_val and new_val.
+    """
+    return float(new_val - old_val) / abs(old_val)
+
+
+def generate_difference_report(json1, json2, use_color=True):
+    """
+    Calculate and report the difference between each test of two benchmarks
+    runs specified as 'json1' and 'json2'.
+    """
+    first_col_width = find_longest_name(json1['benchmarks']) + 5
+    def find_test(name):
+        for b in json2['benchmarks']:
+            if b['name'] == name:
+                return b
+        return None
+    first_line = "{:<{}s}     Time           CPU".format(
+        'Benchmark', first_col_width)
+    output_strs = [first_line, '-' * len(first_line)]
+    for bn in json1['benchmarks']:
+        other_bench = find_test(bn['name'])
+        if not other_bench:
+            continue
+
+        def get_color(res):
+            if res > 0.05:
+                return BC_FAIL
+            elif res > -0.07:
+                return BC_WHITE
+            else:
+                return BC_CYAN
+        fmt_str = "{}{:<{}s}{endc}    {}{:+.2f}{endc}         {}{:+.2f}{endc}"
+        tres = calculate_change(bn['real_time'], other_bench['real_time'])
+        cpures = calculate_change(bn['cpu_time'], other_bench['cpu_time'])
+        output_strs += [color_format(use_color, fmt_str,
+            BC_HEADER, bn['name'], first_col_width,
+            get_color(tres), tres, get_color(cpures), cpures,
+            endc=BC_ENDC)]
+    return output_strs
+
+###############################################################################
+# Unit tests
+
+import unittest
+
+class TestReportDifference(unittest.TestCase):
+    def load_results(self):
+        import json
+        testInputs = os.path.join(os.path.dirname(os.path.realpath(__file__)), 
'Inputs')
+        testOutput1 = os.path.join(testInputs, 'test1_run1.json')
+        testOutput2 = os.path.join(testInputs, 'test1_run2.json')
+        with open(testOutput1, 'r') as f:
+            json1 = json.load(f)
+        with open(testOutput2, 'r') as f:
+            json2 = json.load(f)
+        return json1, json2
+
+    def test_basic(self):
+        expect_lines = [
+            ['BM_SameTimes', '+0.00', '+0.00'],
+            ['BM_2xFaster', '-0.50', '-0.50'],
+            ['BM_2xSlower', '+1.00', '+1.00'],
+            ['BM_10PercentFaster', '-0.10', '-0.10'],
+            ['BM_10PercentSlower', '+0.10', '+0.10']
+        ]
+        json1, json2 = self.load_results()
+        output_lines = generate_difference_report(json1, json2, 
use_color=False)
+        print output_lines
+        self.assertEqual(len(output_lines), len(expect_lines))
+        for i in xrange(0, len(output_lines)):
+            parts = [x for x in output_lines[i].split(' ') if x]
+            self.assertEqual(len(parts), 3)
+            self.assertEqual(parts, expect_lines[i])
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: libcxx/trunk/utils/google-benchmark/tools/gbench/util.py
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/google-benchmark/tools/gbench/util.py?rev=278147&view=auto
==============================================================================
--- libcxx/trunk/utils/google-benchmark/tools/gbench/util.py (added)
+++ libcxx/trunk/utils/google-benchmark/tools/gbench/util.py Tue Aug  9 
13:56:48 2016
@@ -0,0 +1,130 @@
+"""util.py - General utilities for running, loading, and processing benchmarks
+"""
+import json
+import os
+import tempfile
+import subprocess
+import sys
+
+# Input file type enumeration
+IT_Invalid    = 0
+IT_JSON       = 1
+IT_Executable = 2
+
+_num_magic_bytes = 2 if sys.platform.startswith('win') else 4
+def is_executable_file(filename):
+    """
+    Return 'True' if 'filename' names a valid file which is likely
+    an executable. A file is considered an executable if it starts with the
+    magic bytes for a EXE, Mach O, or ELF file.
+    """
+    if not os.path.isfile(filename):
+        return False
+    with open(filename, 'r') as f:
+        magic_bytes = f.read(_num_magic_bytes)
+    if sys.platform == 'darwin':
+        return magic_bytes in [
+            '\xfe\xed\xfa\xce',  # MH_MAGIC
+            '\xce\xfa\xed\xfe',  # MH_CIGAM
+            '\xfe\xed\xfa\xcf',  # MH_MAGIC_64
+            '\xcf\xfa\xed\xfe',  # MH_CIGAM_64
+            '\xca\xfe\xba\xbe',  # FAT_MAGIC
+            '\xbe\xba\xfe\xca'   # FAT_CIGAM
+        ]
+    elif sys.platform.startswith('win'):
+        return magic_bytes == 'MZ'
+    else:
+        return magic_bytes == '\x7FELF'
+
+
+def is_json_file(filename):
+    """
+    Returns 'True' if 'filename' names a valid JSON output file.
+    'False' otherwise.
+    """
+    try:
+        with open(filename, 'r') as f:
+            json.load(f)
+        return True
+    except:
+        pass
+    return False
+
+
+def classify_input_file(filename):
+    """
+    Return a tuple (type, msg) where 'type' specifies the classified type
+    of 'filename'. If 'type' is 'IT_Invalid' then 'msg' is a human readable
+    string represeting the error.
+    """
+    ftype = IT_Invalid
+    err_msg = None
+    if not os.path.exists(filename):
+        err_msg = "'%s' does not exist" % filename
+    elif not os.path.isfile(filename):
+        err_msg = "'%s' does not name a file" % filename
+    elif is_executable_file(filename):
+        ftype = IT_Executable
+    elif is_json_file(filename):
+        ftype = IT_JSON
+    else:
+        err_msg = "'%s' does not name a valid benchmark executable or JSON 
file"
+    return ftype, err_msg
+
+
+def check_input_file(filename):
+    """
+    Classify the file named by 'filename' and return the classification.
+    If the file is classified as 'IT_Invalid' print an error message and exit
+    the program.
+    """
+    ftype, msg = classify_input_file(filename)
+    if ftype == IT_Invalid:
+        print "Invalid input file: %s" % msg
+        sys.exit(1)
+    return ftype
+
+
+def load_benchmark_results(fname):
+    """
+    Read benchmark output from a file and return the JSON object.
+    REQUIRES: 'fname' names a file containing JSON benchmark output.
+    """
+    with open(fname, 'r') as f:
+        return json.load(f)
+
+
+def run_benchmark(exe_name, benchmark_flags):
+    """
+    Run a benchmark specified by 'exe_name' with the specified
+    'benchmark_flags'. The benchmark is run directly as a subprocess to 
preserve
+    real time console output.
+    RETURNS: A JSON object representing the benchmark output
+    """
+    thandle, tname = tempfile.mkstemp()
+    os.close(thandle)
+    cmd = [exe_name] + benchmark_flags
+    print("RUNNING: %s" % ' '.join(cmd))
+    exitCode = subprocess.call(cmd + ['--benchmark_out=%s' % tname])
+    if exitCode != 0:
+        print('TEST FAILED...')
+        sys.exit(exitCode)
+    json_res = load_benchmark_results(tname)
+    os.unlink(tname)
+    return json_res
+
+
+def run_or_load_benchmark(filename, benchmark_flags):
+    """
+    Get the results for a specified benchmark. If 'filename' specifies
+    an executable benchmark then the results are generated by running the
+    benchmark. Otherwise 'filename' must name a valid JSON output file,
+    which is loaded and the result returned.
+    """
+    ftype = check_input_file(filename)
+    if ftype == IT_JSON:
+        return load_benchmark_results(filename)
+    elif ftype == IT_Executable:
+        return run_benchmark(filename, benchmark_flags)
+    else:
+        assert False # This branch is unreachable
\ No newline at end of file


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to