Add 'benchmark::DoNotOptimize(...)' to help users prevent optimizations
diff --git a/README.md b/README.md
index 553e34a..4c0d77a 100644
--- a/README.md
+++ b/README.md
@@ -160,6 +160,19 @@
   }
 }
 BENCHMARK(BM_MultiThreaded)->Threads(2);
+
+To prevent a value or expression from being optimized away by the compiler
+the `benchmark::DoNotOptimize(...)` function can be used.
+
+```c++
+static void BM_test(benchmark::State& state) {
+  while (state.KeepRunning()) {
+      int x = 0;
+      for (int i=0; i < 64; ++i) {
+        benchmark::DoNotOptimize(x += i);
+      }
+  }
+}
 ```
 
 
diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h
index 340ef6f..ed55c88 100644
--- a/include/benchmark/benchmark_api.h
+++ b/include/benchmark/benchmark_api.h
@@ -174,8 +174,27 @@
     typedef int type;
 };
 
+void UseCharPointer(char const volatile*);
+
 } // end namespace internal
 
+// The DoNotOptimize(...) function can be used to prevent a value or
+// expression from being optimized away by the compiler. This function is
+// intented to add little to no overhead.
+// See: http://stackoverflow.com/questions/28287064
+#if defined(__GNUC__)
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
+    asm volatile("" : "+r" (const_cast<Tp&>(value)));
+}
+#else
+template <class Tp>
+inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
+    internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
+}
+#endif
+
+
 // State is passed to a running Benchmark and contains state for the
 // benchmark to use.
 class State {
diff --git a/src/benchmark.cc b/src/benchmark.cc
index 5fc149b..9643a2a 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -73,6 +73,8 @@
 
 namespace internal {
 
+void UseCharPointer(char const volatile*) {}
+
 // NOTE: This is a dummy "mutex" type used to denote the actual mutex
 // returned by GetBenchmarkLock(). This is only used to placate the thread
 // safety warnings by giving the return of GetBenchmarkLock() a name.
diff --git a/test/basic_test.cc b/test/basic_test.cc
index fedcf08..f7b45be 100644
--- a/test/basic_test.cc
+++ b/test/basic_test.cc
@@ -8,8 +8,7 @@
 
 void BM_empty(benchmark::State& state) {
   while (state.KeepRunning()) {
-    volatile std::size_t x = state.iterations();
-    ((void)x);
+    benchmark::DoNotOptimize(state.iterations());
   }
 }
 BENCHMARK(BM_empty);
@@ -18,8 +17,7 @@
 void BM_spin_empty(benchmark::State& state) {
   while (state.KeepRunning()) {
     for (int x = 0; x < state.range_x(); ++x) {
-      volatile int dummy = x;
-      ((void)dummy);
+      benchmark::DoNotOptimize(x);
     }
   }
 }
@@ -28,13 +26,11 @@
 
 void BM_spin_pause_before(benchmark::State& state) {
   for (int i = 0; i < state.range_x(); ++i) {
-    volatile int dummy = i;
-    ((void)dummy);
+    benchmark::DoNotOptimize(i);
   }
   while(state.KeepRunning()) {
     for (int i = 0; i < state.range_x(); ++i) {
-      volatile int dummy = i;
-      ((void)dummy);
+      benchmark::DoNotOptimize(i);
     }
   }
 }
@@ -46,13 +42,11 @@
   while(state.KeepRunning()) {
     state.PauseTiming();
     for (int i = 0; i < state.range_x(); ++i) {
-      volatile int dummy = i;
-      ((void)dummy);
+      benchmark::DoNotOptimize(i);
     }
     state.ResumeTiming();
     for (int i = 0; i < state.range_x(); ++i) {
-      volatile int dummy = i;
-      ((void)dummy);
+      benchmark::DoNotOptimize(i);
     }
   }
 }
@@ -81,13 +75,11 @@
 void BM_spin_pause_after(benchmark::State& state) {
   while(state.KeepRunning()) {
     for (int i = 0; i < state.range_x(); ++i) {
-      volatile int dummy = i;
-      ((void)dummy);
+      benchmark::DoNotOptimize(i);
     }
   }
   for (int i = 0; i < state.range_x(); ++i) {
-    volatile int dummy = i;
-    ((void)dummy);
+    benchmark::DoNotOptimize(i);
   }
 }
 BASIC_BENCHMARK_TEST(BM_spin_pause_after);
@@ -96,18 +88,15 @@
 
 void BM_spin_pause_before_and_after(benchmark::State& state) {
   for (int i = 0; i < state.range_x(); ++i) {
-    volatile int dummy = i;
-    ((void)dummy);
+    benchmark::DoNotOptimize(i);
   }
   while(state.KeepRunning()) {
     for (int i = 0; i < state.range_x(); ++i) {
-      volatile int dummy = i;
-      ((void)dummy);
+      benchmark::DoNotOptimize(i);
     }
   }
   for (int i = 0; i < state.range_x(); ++i) {
-    volatile int dummy = i;
-    ((void)dummy);
+    benchmark::DoNotOptimize(i);
   }
 }
 BASIC_BENCHMARK_TEST(BM_spin_pause_before_and_after);
diff --git a/test/benchmark_test.cc b/test/benchmark_test.cc
index f5abe61..2fb3355 100644
--- a/test/benchmark_test.cc
+++ b/test/benchmark_test.cc
@@ -84,9 +84,8 @@
 
 static void BM_CalculatePi(benchmark::State& state) {
   static const int depth = 1024;
-  double pi BENCHMARK_UNUSED = 0.0;
   while (state.KeepRunning()) {
-    pi = CalculatePi(depth);
+    benchmark::DoNotOptimize(CalculatePi(depth));
   }
 }
 BENCHMARK(BM_CalculatePi)->Threads(8);
@@ -129,11 +128,8 @@
 static void BM_StringCompare(benchmark::State& state) {
   std::string s1(state.range_x(), '-');
   std::string s2(state.range_x(), '-');
-  int r = 0;
   while (state.KeepRunning())
-    r |= s1.compare(s2);
-  // Prevent compiler optimizations
-  assert(r != std::numeric_limits<int>::max());
+    benchmark::DoNotOptimize(s1.compare(s2));
 }
 BENCHMARK(BM_StringCompare)->Range(1, 1<<20);
 
@@ -159,10 +155,10 @@
 
 static void BM_LongTest(benchmark::State& state) {
   double tracker = 0.0;
-  while (state.KeepRunning())
+  while (state.KeepRunning()) {
     for (int i = 0; i < state.range_x(); ++i)
-      tracker += i;
-  assert(tracker > 1.0);
+      benchmark::DoNotOptimize(tracker += i);
+  }
 }
 BENCHMARK(BM_LongTest)->Range(1<<16,1<<28);