Improve performance of constructing filesystem::path from strings.

This patch fixes a performance bug when constructing or appending to a path
from a string or c-string. Previously we called 'push_back' to append every
single character. This caused multiple re-allocation and copies when at most
one reallocation is necessary. The new behavior is to simply call
`string::append` so it can correctly handle reallocation.

For large strings this change is a ~4x improvement. This also makes our path
faster to construct than libstdc++'s.

llvm-svn: 285530
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: ef915d3ef476f9de691300b6c6f9862b6b5607f8
diff --git a/benchmarks/filesystem.bench.cpp b/benchmarks/filesystem.bench.cpp
index 8dacbe6..2cea3f6 100644
--- a/benchmarks/filesystem.bench.cpp
+++ b/benchmarks/filesystem.bench.cpp
@@ -21,11 +21,27 @@
     benchmark::DoNotOptimize(P.native().data());
   }
 }
-BENCHMARK_CAPTURE(BM_PathConstructString, iterate_elements,
+BENCHMARK_CAPTURE(BM_PathConstructString, large_string,
   getRandomStringInputs)->Arg(TestNumInputs);
 
 
 template <class GenInputs>
+void BM_PathConstructCStr(benchmark::State &st, GenInputs gen) {
+  using namespace fs;
+  const auto in = gen(st.range(0));
+  path PP;
+  for (auto& Part : in)
+    PP /= Part;
+  benchmark::DoNotOptimize(PP.native().data());
+  while (st.KeepRunning()) {
+    const path P(PP.native().c_str());
+    benchmark::DoNotOptimize(P.native().data());
+  }
+}
+BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string,
+  getRandomStringInputs)->Arg(TestNumInputs);
+
+template <class GenInputs>
 void BM_PathIterateMultipleTimes(benchmark::State &st, GenInputs gen) {
   using namespace fs;
   const auto in = gen(st.range(0));
@@ -85,6 +101,4 @@
 BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements,
   getRandomStringInputs)->Arg(TestNumInputs);
 
-
-
 BENCHMARK_MAIN()