Introduce StringBuilder utility around raw_string_ostream

Alp Toker alp at nuanti.com
Tue Jul 1 02:58:32 PDT 2014


On 01/07/2014 10:44, Benjamin Kramer wrote:
> On Tue, Jul 1, 2014 at 1:17 AM, Alp Toker <alp at nuanti.com> wrote:
>> On 01/07/2014 01:12, Chandler Carruth wrote:
>>> Just as a very small correction to some of the facts here:
>>>
>>> On Mon, Jun 30, 2014 at 2:24 PM, Alp Toker <alp at nuanti.com
>>> <mailto:alp at nuanti.com>> wrote:
>>>
>>>      1) Uses a non-heap container (SmallString) by default.
>>>
>>>
>>> std::string has a small-string optimization in both libc++ and, whenever
>>> GCC takes the ABI break and conforms with C++11, libstdc++
>>
>> That's an optimization for strings less than 10-22 characters, and is
>> libc++-specific. Worst of all it's non-customizable and pessimal, say, if we
>> *know* the string is likely to be, say, 40 bytes at a certain point-of-use.
>>
>> Examining the hundreds of SmallStrings in the LLVM code base, only a handful
>> out of those would benefit in any way from libc++'s small string feature
>> with the remainder thrashing the heap. The proposed patch does a great job
>> with all of them.
>>
> The reason why most of them are instantiated for 128 bytes is that
> raw_svector_ostream allocates a buffer of at least 128 bytes which
> makes smaller SmallStrings useless. The actual string stored will be
> much smaller most of the time.

Indeed, providing a buffer smaller than 128 bytes to raw_svector_ostream 
is useless and likely inefficient as well:

   /// \param O The vector to write to; this should generally have at 
least 128
   /// bytes free to avoid any extraneous memory overhead.

The reason:

   // Set up the initial external buffer. We make sure that the buffer 
has at
   // least 128 bytes free; raw_ostream itself only requires 64, but we 
want to
   // make sure that we don't grow the buffer unnecessarily on 
destruction (when
   // the data is flushed). See the FIXME below.

So it's in fact a bug workaround that users have to specify 128 bytes.

Unfortunately the users *don't* get it right, e.g.:

-  SmallVector<char, 64> InsnStr;
-  raw_svector_ostream Annotations(InsnStr);

The good news is that we can hide this with the new small_string_ostream:

  template <unsigned InternalLen>
  class small_string_ostream : public raw_svector_ostream {
     SmallVector<char, (InternalLen > MinBuffer ? InternalLen : 
MinBuffer)> Buffer;
     ...
}

Therefore when the above is converted to use the new utility...

+  small_string_ostream<64> Annotations;

... it'll get instantiated to the recommended buffer size and therefore 
avoid inefficiency, fixing existing code without requiring users to 
account for the flush() bug.

And when the bug is fixed (should be straightforward to avoid the 
allocate-on-finalize), that improvement will propagate without having to 
examine each of the uses.

I've attached an updated patch incorporating the above. This is another 
great example of an optimization that was getting missed before which we 
can now handle elegantly.

Alp.


>
> - Ben
>
>>> So you don't have to use SmallString to avoid heap allocations. The
>>> primary advantage of SmallString is the ability to customize how many bytes
>>> are available in the internal buffer.
>>
>> Yes, the proposed patch frequently overrides the suggested 128 byte stack
>> buffer size in cases where we have a better idea how large our string will
>> be.
>>
>> I'm familiar with libc++ and other standard C++ libraries, and basically
>> don't see any overlap with the string facilities provided there. As Yaron
>> pointed out, this is much more a natural continuation of ADT's data types.
>>
>> Alp.
>>
>>
>>
>> --
>> http://www.nuanti.com
>> the browser experts
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-- 
http://www.nuanti.com
the browser experts

-------------- next part --------------
diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h
index e6d2ed1..759afca 100644
--- a/include/llvm/Analysis/CFGPrinter.h
+++ b/include/llvm/Analysis/CFGPrinter.h
@@ -36,9 +36,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
     if (!Node->getName().empty())
       return Node->getName().str();
 
-    std::string Str;
-    raw_string_ostream OS(Str);
-
+    string_ostream OS;
     Node->printAsOperand(OS, false);
     return OS.str();
   }
@@ -46,8 +44,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
   static std::string getCompleteNodeLabel(const BasicBlock *Node,
                                           const Function *) {
     enum { MaxColumns = 80 };
-    std::string Str;
-    raw_string_ostream OS(Str);
+    string_ostream OS;
 
     if (Node->getName().empty()) {
       Node->printAsOperand(OS, false);
@@ -109,8 +106,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
 
       if (SuccNo == 0) return "def";
 
-      std::string Str;
-      raw_string_ostream OS(Str);
+      string_ostream OS;
       SwitchInst::ConstCaseIt Case =
           SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
       OS << Case.getCaseValue()->getValue();
diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h
index 6221d3b..430beff 100644
--- a/include/llvm/ExecutionEngine/ObjectBuffer.h
+++ b/include/llvm/ExecutionEngine/ObjectBuffer.h
@@ -59,23 +59,18 @@ protected:
 class ObjectBufferStream : public ObjectBuffer {
   void anchor() override;
 public:
-  ObjectBufferStream() : OS(SV) {}
+  ObjectBufferStream() {}
   virtual ~ObjectBufferStream() {}
 
   raw_ostream &getOStream() { return OS; }
   void flush()
   {
-    OS.flush();
-
     // Make the data accessible via the ObjectBuffer::Buffer
-    Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()),
-                                            "",
-                                            false));
+    Buffer.reset(MemoryBuffer::getMemBuffer(OS.str(), "", false));
   }
 
 protected:
-  SmallVector<char, 4096> SV; // Working buffer into which we JIT.
-  raw_svector_ostream     OS; // streaming wrapper
+  small_string_ostream<4096> OS; // Working buffer into which we JIT.
 };
 
 } // namespace llvm
diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h
index 2f02aa7..a6bd1af 100644
--- a/include/llvm/Support/GraphWriter.h
+++ b/include/llvm/Support/GraphWriter.h
@@ -184,8 +184,7 @@ public:
         O << "|" << DOT::EscapeString(NodeDesc);
     }
 
-    std::string edgeSourceLabels;
-    raw_string_ostream EdgeSourceLabels(edgeSourceLabels);
+    string_ostream EdgeSourceLabels;
     bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels, Node);
 
     if (hasEdgeSourceLabels) {
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index a23faf6..14ca2db 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -612,8 +612,7 @@ template<typename T>
 typename std::enable_if<has_ScalarTraits<T>::value,void>::type
 yamlize(IO &io, T &Val, bool) {
   if ( io.outputting() ) {
-    std::string Storage;
-    llvm::raw_string_ostream Buffer(Storage);
+    llvm::string_ostream Buffer;
     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
     StringRef Str = Buffer.str();
     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index 34fbe08..e9e59ab 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -15,13 +15,12 @@
 #define LLVM_SUPPORT_RAW_OSTREAM_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataTypes.h"
 
 namespace llvm {
   class format_object_base;
-  template <typename T>
-  class SmallVectorImpl;
 
   namespace sys {
     namespace fs {
@@ -461,11 +460,23 @@ class raw_svector_ostream : public raw_ostream {
   /// current_pos - Return the current position within the stream, not
   /// counting the bytes currently in the buffer.
   uint64_t current_pos() const override;
+
+protected:
+  // This constructor is specified not to access \p O provided for storage as it
+  // may not yet be initialized at construction time.
+  explicit raw_svector_ostream(SmallVectorImpl<char> &O, std::nullptr_t)
+      : OS(O){};
+  void init();
+
 public:
+  /// The recommended minimum number of bytes free to avoid any extraneous
+  /// memory overhead.
+  static const size_t MinBuffer = 128;
+
   /// Construct a new raw_svector_ostream.
   ///
-  /// \param O The vector to write to; this should generally have at least 128
-  /// bytes free to avoid any extraneous memory overhead.
+  /// \param O The vector to write to; this should generally have at least
+  /// \c MinBuffer bytes free.
   explicit raw_svector_ostream(SmallVectorImpl<char> &O);
   ~raw_svector_ostream();
 
@@ -493,6 +504,26 @@ public:
   ~raw_null_ostream();
 };
 
+/// string_ostream - A raw_ostream that builds a string.  This is a
+/// raw_svector_ostream with storage.
+template <unsigned InternalLen>
+class small_string_ostream : public raw_svector_ostream {
+  SmallVector<char, (InternalLen > MinBuffer ? InternalLen : MinBuffer)> Buffer;
+  // There's no need to flush/resync explicitly.
+  using raw_svector_ostream::flush;
+  using raw_svector_ostream::resync;
+
+public:
+  small_string_ostream() : raw_svector_ostream(Buffer, nullptr) { init(); }
+
+  void clear() {
+    flush();
+    Buffer.clear();
+  }
+};
+
+typedef small_string_ostream<raw_svector_ostream::MinBuffer> string_ostream;
+
 } // end llvm namespace
 
 #endif
diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h
index c924bd8..01829a1 100644
--- a/include/llvm/TableGen/StringToOffsetTable.h
+++ b/include/llvm/TableGen/StringToOffsetTable.h
@@ -42,8 +42,8 @@ public:
 
   void EmitString(raw_ostream &O) {
     // Escape the string.
-    SmallString<256> Str;
-    raw_svector_ostream(Str).write_escaped(AggregateString);
+    small_string_ostream<256> Str;
+    Str.write_escaped(AggregateString);
     AggregateString = Str.str();
 
     O << "    \"";
diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp
index ade940a..907203c 100644
--- a/lib/Analysis/Analysis.cpp
+++ b/lib/Analysis/Analysis.cpp
@@ -75,8 +75,7 @@ void LLVMInitializeAnalysis(LLVMPassRegistryRef R) {
 LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action,
                           char **OutMessages) {
   raw_ostream *DebugOS = Action != LLVMReturnStatusAction ? &errs() : nullptr;
-  std::string Messages;
-  raw_string_ostream MsgsOS(Messages);
+  string_ostream MsgsOS;
 
   LLVMBool Result = verifyModule(*unwrap(M), OutMessages ? &MsgsOS : DebugOS);
 
@@ -87,8 +86,10 @@ LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action,
   if (Action == LLVMAbortProcessAction && Result)
     report_fatal_error("Broken module found, compilation aborted!");
 
-  if (OutMessages)
-    *OutMessages = strdup(MsgsOS.str().c_str());
+  if (OutMessages) {
+    MsgsOS << '\0';
+    *OutMessages = strdup(MsgsOS.str().data());
+  }
 
   return Result;
 }
diff --git a/lib/Analysis/BlockFrequencyInfo.cpp b/lib/Analysis/BlockFrequencyInfo.cpp
index 8ed8e3e..7e702c3 100644
--- a/lib/Analysis/BlockFrequencyInfo.cpp
+++ b/lib/Analysis/BlockFrequencyInfo.cpp
@@ -82,10 +82,9 @@ struct DOTGraphTraits<BlockFrequencyInfo*> : public DefaultDOTGraphTraits {
 
   std::string getNodeLabel(const BasicBlock *Node,
                            const BlockFrequencyInfo *Graph) {
-    std::string Result;
-    raw_string_ostream OS(Result);
+    string_ostream OS;
 
-    OS << Node->getName().str() << ":";
+    OS << Node->getName() << ":";
     switch (ViewBlockFreqPropagationDAG) {
     case GVDT_Fraction:
       Graph->printBlockFreq(OS, Node);
@@ -98,7 +97,7 @@ struct DOTGraphTraits<BlockFrequencyInfo*> : public DefaultDOTGraphTraits {
                        "never reach this point.");
     }
 
-    return Result;
+    return OS.str();
   }
 };
 
diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp
index b14f329..806a1fd 100644
--- a/lib/Analysis/Lint.cpp
+++ b/lib/Analysis/Lint.cpp
@@ -105,11 +105,10 @@ namespace {
     const DataLayout *DL;
     TargetLibraryInfo *TLI;
 
-    std::string Messages;
-    raw_string_ostream MessagesStr;
+    string_ostream MessagesStr;
 
     static char ID; // Pass identification, replacement for typeid
-    Lint() : FunctionPass(ID), MessagesStr(Messages) {
+    Lint() : FunctionPass(ID) {
       initializeLintPass(*PassRegistry::getPassRegistry());
     }
 
@@ -181,7 +180,7 @@ bool Lint::runOnFunction(Function &F) {
   TLI = &getAnalysis<TargetLibraryInfo>();
   visit(F);
   dbgs() << MessagesStr.str();
-  Messages.clear();
+  MessagesStr.clear();
   return false;
 }
 
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index be55ac6..6f330d8 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -28,10 +28,9 @@
 using namespace llvm;
 
 static std::string getTypeString(Type *T) {
-  std::string Result;
-  raw_string_ostream Tmp(Result);
-  Tmp << *T;
-  return Tmp.str();
+  string_ostream Result;
+  Result << *T;
+  return Result.str();
 }
 
 /// Run: module ::= toplevelentity*
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 5a809aa..f004cdb 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1584,8 +1584,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) {
 
     // Otherwise report the problem to the user.
     {
-      std::string S;
-      raw_string_ostream OS(S);
+      string_ostream OS;
       OS << "Unsupported expression in static initializer: ";
       CE->printAsOperand(OS, /*PrintType=*/false,
                      !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 46ee0c8..01f26d0 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -241,8 +241,7 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
         }
       }
       if (Error) {
-        std::string msg;
-        raw_string_ostream Msg(msg);
+        string_ostream Msg;
         Msg << "invalid operand in inline asm: '" << AsmStr << "'";
         MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
       }
@@ -413,8 +412,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
           }
         }
         if (Error) {
-          std::string msg;
-          raw_string_ostream Msg(msg);
+          string_ostream Msg;
           Msg << "invalid operand in inline asm: '" << AsmStr << "'";
           MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
         }
@@ -471,8 +469,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
 
   // Emit the inline asm to a temporary string so we can emit it through
   // EmitInlineAsm.
-  SmallString<256> StringData;
-  raw_svector_ostream OS(StringData);
+  small_string_ostream<256> OS;
 
   // The variant of the current asmprinter.
   int AsmPrinterVariant = MAI->getAssemblerDialect();
@@ -517,8 +514,7 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
     }
     OS << Counter;
   } else {
-    std::string msg;
-    raw_string_ostream Msg(msg);
+    string_ostream Msg;
     Msg << "Unknown special formatter '" << Code
          << "' for machine instr: " << *MI;
     report_fatal_error(Msg.str());
diff --git a/lib/CodeGen/MachineBlockFrequencyInfo.cpp b/lib/CodeGen/MachineBlockFrequencyInfo.cpp
index 9151d99..35e4a56 100644
--- a/lib/CodeGen/MachineBlockFrequencyInfo.cpp
+++ b/lib/CodeGen/MachineBlockFrequencyInfo.cpp
@@ -89,10 +89,9 @@ struct DOTGraphTraits<MachineBlockFrequencyInfo*> :
 
   std::string getNodeLabel(const MachineBasicBlock *Node,
                            const MachineBlockFrequencyInfo *Graph) {
-    std::string Result;
-    raw_string_ostream OS(Result);
+    string_ostream OS;
 
-    OS << Node->getName().str() << ":";
+    OS << Node->getName() << ":";
     switch (ViewMachineBlockFreqPropagationDAG) {
     case GVDT_Fraction:
       Graph->printBlockFreq(OS, Node);
@@ -105,7 +104,7 @@ struct DOTGraphTraits<MachineBlockFrequencyInfo*> :
                        "never reach this point.");
     }
 
-    return Result;
+    return OS.str();
   }
 };
 
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp
index 74af1e2..891f605 100644
--- a/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/lib/CodeGen/MachineBlockPlacement.cpp
@@ -264,23 +264,19 @@ INITIALIZE_PASS_END(MachineBlockPlacement, "block-placement2",
 ///
 /// Only used by debug logging.
 static std::string getBlockName(MachineBasicBlock *BB) {
-  std::string Result;
-  raw_string_ostream OS(Result);
+  string_ostream OS;
   OS << "BB#" << BB->getNumber()
      << " (derived from LLVM BB '" << BB->getName() << "')";
-  OS.flush();
-  return Result;
+  return OS.str();
 }
 
 /// \brief Helper to print the number of a MBB.
 ///
 /// Only used by debug logging.
 static std::string getBlockNum(MachineBasicBlock *BB) {
-  std::string Result;
-  raw_string_ostream OS(Result);
+  string_ostream OS;
   OS << "BB#" << BB->getNumber();
-  OS.flush();
-  return Result;
+  return OS.str();
 }
 #endif
 
diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index 6138aef..20210ad 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/lib/CodeGen/MachineFunction.cpp
@@ -465,9 +465,8 @@ MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx,
 
   const char *Prefix = isLinkerPrivate ? DL->getLinkerPrivateGlobalPrefix() :
                                          DL->getPrivateGlobalPrefix();
-  SmallString<60> Name;
-  raw_svector_ostream(Name)
-    << Prefix << "JTI" << getFunctionNumber() << '_' << JTI;
+  small_string_ostream<60> Name;
+  Name << Prefix << "JTI" << getFunctionNumber() << '_' << JTI;
   return Ctx.GetOrCreateSymbol(Name.str());
 }
 
diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp
index 5b5b3f3..826f84e 100644
--- a/lib/CodeGen/MachineScheduler.cpp
+++ b/lib/CodeGen/MachineScheduler.cpp
@@ -3245,8 +3245,7 @@ struct DOTGraphTraits<ScheduleDAGMI*> : public DefaultDOTGraphTraits {
   }
 
   static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G) {
-    std::string Str;
-    raw_string_ostream SS(Str);
+    string_ostream SS;
     const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
     const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
       static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index 92a9a30..baf4af6 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -1197,8 +1197,7 @@ void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const {
 }
 
 std::string ScheduleDAGInstrs::getGraphNodeLabel(const SUnit *SU) const {
-  std::string s;
-  raw_string_ostream oss(s);
+  string_ostream oss;
   if (SU == &EntrySU)
     oss << "<entry>";
   else if (SU == &ExitSU)
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 57e22e2..a2cc290 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3245,8 +3245,7 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
 
 
 void SelectionDAGISel::CannotYetSelect(SDNode *N) {
-  std::string msg;
-  raw_string_ostream Msg(msg);
+  string_ostream Msg;
   Msg << "Cannot select: ";
 
   if (N->getOpcode() != ISD::INTRINSIC_W_CHAIN &&
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp
index 4df5ede..680a7ec 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp
@@ -268,8 +268,7 @@ void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {
 }
 
 std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {
-  std::string s;
-  raw_string_ostream O(s);
+  string_ostream O;
   O << "SU(" << SU->NodeNum << "): ";
   if (SU->getNode()) {
     SmallVector<SDNode *, 4> GluedNodes;
diff --git a/lib/CodeGen/TargetSchedule.cpp b/lib/CodeGen/TargetSchedule.cpp
index b0f2ca6..d18a514 100644
--- a/lib/CodeGen/TargetSchedule.cpp
+++ b/lib/CodeGen/TargetSchedule.cpp
@@ -212,11 +212,10 @@ unsigned TargetSchedModel::computeOperandLatency(
   if (SCDesc->isValid() && !DefMI->getOperand(DefOperIdx).isImplicit()
       && !DefMI->getDesc().OpInfo[DefOperIdx].isOptionalDef()
       && SchedModel.isComplete()) {
-    std::string Err;
-    raw_string_ostream ss(Err);
-    ss << "DefIdx " << DefIdx << " exceeds machine model writes for "
-       << *DefMI;
-    report_fatal_error(ss.str());
+    string_ostream Err;
+    Err << "DefIdx " << DefIdx << " exceeds machine model writes for "
+        << *DefMI;
+    report_fatal_error(Err.str());
   }
 #endif
   // FIXME: Automatically giving all implicit defs defaultDefLatency is
diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp
index a33548e..2227260 100644
--- a/lib/DebugInfo/DWARFDebugFrame.cpp
+++ b/lib/DebugInfo/DWARFDebugFrame.cpp
@@ -353,10 +353,9 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
 
     if (Offset != EndStructureOffset) {
-      std::string Str;
-      raw_string_ostream OS(Str);
-      OS << format("Parsing entry instructions at %lx failed", StartOffset);
-      report_fatal_error(Str);
+      string_ostream Str;
+      Str << format("Parsing entry instructions at %lx failed", StartOffset);
+      report_fatal_error(Str.str());
     }
   }
 }
diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index 0cb781c..a355844 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -62,6 +62,11 @@ void LLVMShutdown() {
 
 /*===-- Error handling ----------------------------------------------------===*/
 
+static char *LLVMCreateMessage(string_ostream &OS) {
+  OS << '\0';
+  return strdup(OS.str().data());
+}
+
 char *LLVMCreateMessage(const char *Message) {
   return strdup(Message);
 }
@@ -110,14 +115,10 @@ unsigned LLVMGetMDKindID(const char* Name, unsigned SLen) {
 }
 
 char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI) {
-  std::string MsgStorage;
-  raw_string_ostream Stream(MsgStorage);
-  DiagnosticPrinterRawOStream DP(Stream);
-
+  string_ostream Msg;
+  DiagnosticPrinterRawOStream DP(Msg);
   unwrap(DI)->print(DP);
-  Stream.flush();
-
-  return LLVMCreateMessage(MsgStorage.c_str());
+  return LLVMCreateMessage(Msg);
 }
 
 LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI){
@@ -201,13 +202,9 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
 }
 
 char *LLVMPrintModuleToString(LLVMModuleRef M) {
-  std::string buf;
-  raw_string_ostream os(buf);
-
+  string_ostream os;
   unwrap(M)->print(os, nullptr);
-  os.flush();
-
-  return strdup(buf.c_str());
+  return LLVMCreateMessage(os);
 }
 
 /*--.. Operations on inline assembler ......................................--*/
@@ -278,17 +275,14 @@ void LLVMDumpType(LLVMTypeRef Ty) {
 }
 
 char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
-  std::string buf;
-  raw_string_ostream os(buf);
+  string_ostream os;
 
   if (unwrap(Ty))
     unwrap(Ty)->print(os);
   else
     os << "Printing <null> Type";
 
-  os.flush();
-
-  return strdup(buf.c_str());
+  return LLVMCreateMessage(os);
 }
 
 /*--.. Operations on integer types .........................................--*/
@@ -532,17 +526,14 @@ void LLVMDumpValue(LLVMValueRef Val) {
 }
 
 char* LLVMPrintValueToString(LLVMValueRef Val) {
-  std::string buf;
-  raw_string_ostream os(buf);
+  string_ostream os;
 
   if (unwrap(Val))
     unwrap(Val)->print(os);
   else
     os << "Printing <null> Value";
 
-  os.flush();
-
-  return strdup(buf.c_str());
+  return LLVMCreateMessage(os);
 }
 
 void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) {
diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp
index dea05fb..3aa7750 100644
--- a/lib/IR/DataLayout.cpp
+++ b/lib/IR/DataLayout.cpp
@@ -519,8 +519,7 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
 }
 
 std::string DataLayout::getStringRepresentation() const {
-  std::string Result;
-  raw_string_ostream OS(Result);
+  string_ostream OS;
 
   OS << (LittleEndian ? "e" : "E");
 
diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp
index de825f0..201b278 100644
--- a/lib/IR/LLVMContext.cpp
+++ b/lib/IR/LLVMContext.cpp
@@ -164,23 +164,22 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) {
   }
 
   // Otherwise, print the message with a prefix based on the severity.
-  std::string MsgStorage;
-  raw_string_ostream Stream(MsgStorage);
-  DiagnosticPrinterRawOStream DP(Stream);
+  string_ostream Msg;
+  DiagnosticPrinterRawOStream DP(Msg);
   DI.print(DP);
-  Stream.flush();
+
   switch (DI.getSeverity()) {
   case DS_Error:
-    errs() << "error: " << MsgStorage << "\n";
+    errs() << "error: " << Msg.str() << "\n";
     exit(1);
   case DS_Warning:
-    errs() << "warning: " << MsgStorage << "\n";
+    errs() << "warning: " << Msg.str() << "\n";
     break;
   case DS_Remark:
-    errs() << "remark: " << MsgStorage << "\n";
+    errs() << "remark: " << Msg.str() << "\n";
     break;
   case DS_Note:
-    errs() << "note: " << MsgStorage << "\n";
+    errs() << "note: " << Msg.str() << "\n";
     break;
   }
 }
diff --git a/lib/IRReader/IRReader.cpp b/lib/IRReader/IRReader.cpp
index 719319d..91d8d22 100644
--- a/lib/IRReader/IRReader.cpp
+++ b/lib/IRReader/IRReader.cpp
@@ -110,13 +110,10 @@ LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef,
 
   if(!*OutM) {
     if (OutMessage) {
-      std::string buf;
-      raw_string_ostream os(buf);
-
+      string_ostream os;
       Diag.print(nullptr, os, false);
-      os.flush();
-
-      *OutMessage = strdup(buf.c_str());
+      os << '\0';
+      *OutMessage = strdup(os.str().data());
     }
     return 1;
   }
diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp
index a1709f6..d87299b 100644
--- a/lib/LTO/LTOCodeGenerator.cpp
+++ b/lib/LTO/LTOCodeGenerator.cpp
@@ -549,16 +549,17 @@ void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
     break;
   }
   // Create the string that will be reported to the external diagnostic handler.
-  std::string MsgStorage;
-  raw_string_ostream Stream(MsgStorage);
-  DiagnosticPrinterRawOStream DP(Stream);
+  string_ostream Msg;
+  DiagnosticPrinterRawOStream DP(Msg);
   DI.print(DP);
-  Stream.flush();
+
+  // Null-terminate the C string.
+  Msg << '\0';
 
   // If this method has been called it means someone has set up an external
   // diagnostic handler. Assert on that.
   assert(DiagHandler && "Invalid diagnostic handler");
-  (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
+  (*DiagHandler)(Severity, Msg.str().data(), DiagContext);
 }
 
 void
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 6973bbb..a51ec5a 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -1175,9 +1175,10 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
   raw_ostream &OS = GetCommentOS();
   SmallString<256> Code;
   SmallVector<MCFixup, 4> Fixups;
-  raw_svector_ostream VecOS(Code);
-  Emitter->EncodeInstruction(Inst, VecOS, Fixups, STI);
-  VecOS.flush();
+  {
+    raw_svector_ostream VecOS(Code);
+    Emitter->EncodeInstruction(Inst, VecOS, Fixups, STI);
+  }
 
   // If we are showing fixups, create symbolic markers in the encoded
   // representation. We do this by making a per-bit map to the fixup item index,
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index cfdab0c..9d32580 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -140,17 +140,15 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
 }
 
 MCSymbol *MCContext::CreateLinkerPrivateTempSymbol() {
-  SmallString<128> NameSV;
-  raw_svector_ostream(NameSV)
-    << MAI->getLinkerPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
-  return CreateSymbol(NameSV);
+  small_string_ostream<128> NameSV;
+  NameSV << MAI->getLinkerPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
+  return CreateSymbol(NameSV.str());
 }
 
 MCSymbol *MCContext::CreateTempSymbol() {
-  SmallString<128> NameSV;
-  raw_svector_ostream(NameSV)
-    << MAI->getPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
-  return CreateSymbol(NameSV);
+  small_string_ostream<128> NameSV;
+  NameSV << MAI->getPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
+  return CreateSymbol(NameSV.str());
 }
 
 unsigned MCContext::NextInstance(unsigned LocalLabelVal) {
diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp
index 0530c26..e3ec4eb 100644
--- a/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/lib/MC/MCDisassembler/Disassembler.cpp
@@ -270,8 +270,7 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
   const MCDisassembler *DisAsm = DC->getDisAsm();
   MCInstPrinter *IP = DC->getIP();
   MCDisassembler::DecodeStatus S;
-  SmallVector<char, 64> InsnStr;
-  raw_svector_ostream Annotations(InsnStr);
+  small_string_ostream<64> Annotations;
   S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC,
                              /*REMOVE*/ nulls(), Annotations);
   switch (S) {
@@ -281,13 +280,10 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
     return 0;
 
   case MCDisassembler::Success: {
-    Annotations.flush();
-    StringRef AnnotationsStr = Annotations.str();
-
     SmallVector<char, 64> InsnStr;
     raw_svector_ostream OS(InsnStr);
     formatted_raw_ostream FormattedOS(OS);
-    IP->printInst(&Inst, FormattedOS, AnnotationsStr);
+    IP->printInst(&Inst, FormattedOS, Annotations.str());
 
     if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
       emitLatency(DC, Inst);
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index bddbf57..eab4d88 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -420,8 +420,7 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
 void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta,
                            uint64_t AddrDelta) {
   MCContext &Context = MCOS->getContext();
-  SmallString<256> Tmp;
-  raw_svector_ostream OS(Tmp);
+  small_string_ostream<256> OS;
   MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OS);
   MCOS->EmitBytes(OS.str());
 }
@@ -1647,8 +1646,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
 void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
                                          uint64_t AddrDelta) {
   MCContext &Context = Streamer.getContext();
-  SmallString<256> Tmp;
-  raw_svector_ostream OS(Tmp);
+  small_string_ostream<256> OS;
   MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
   Streamer.EmitBytes(OS.str());
 }
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index fa5dfdc..7bfbbf4 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -4580,8 +4580,7 @@ bool AsmParser::parseMSInlineAsm(
   }
 
   // Build the IR assembly string.
-  std::string AsmStringIR;
-  raw_string_ostream OS(AsmStringIR);
+  string_ostream OS;
   const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart();
   const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd();
   array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
@@ -4646,8 +4645,7 @@ bool AsmParser::parseMSInlineAsm(
     }
     case AOK_DotOperator:
       // Insert the dot if the user omitted it.
-      OS.flush();
-      if (AsmStringIR.back() != '.')
+      if (OS.str().back() != '.')
         OS << '.';
       OS << AR.Val;
       break;
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 50e7f63..7fd06f7 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -301,7 +301,7 @@ static unsigned getCPUType(const MachOObjectFile *O) {
 
 static void printRelocationTargetName(const MachOObjectFile *O,
                                       const MachO::any_relocation_info &RE,
-                                      raw_string_ostream &fmt) {
+                                      raw_ostream &fmt) {
   bool IsScattered = O->isRelocationScattered(RE);
 
   // Target of a scattered relocation is an address.  In the interest of
@@ -1010,8 +1010,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
 
   unsigned Arch = this->getArch();
 
-  std::string fmtbuf;
-  raw_string_ostream fmt(fmtbuf);
+  string_ostream fmt;
   unsigned Type = this->getAnyRelocationType(RE);
   bool IsPCRel = this->getAnyRelocationPCRel(RE);
 
@@ -1174,7 +1173,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
   } else
     printRelocationTargetName(this, RE, fmt);
 
-  fmt.flush();
+  StringRef fmtbuf = fmt.str();
   Result.append(fmtbuf.begin(), fmtbuf.end());
   return object_error::success;
 }
diff --git a/lib/Option/Arg.cpp b/lib/Option/Arg.cpp
index 4c8da58..30a6922 100644
--- a/lib/Option/Arg.cpp
+++ b/lib/Option/Arg.cpp
@@ -62,8 +62,7 @@ void Arg::dump() const {
 }
 
 std::string Arg::getAsString(const ArgList &Args) const {
-  SmallString<256> Res;
-  llvm::raw_svector_ostream OS(Res);
+  small_string_ostream<256> OS;
 
   ArgStringList ASL;
   render(Args, ASL);
@@ -95,8 +94,7 @@ void Arg::render(const ArgList &Args, ArgStringList &Output) const {
     break;
 
   case Option::RenderCommaJoinedStyle: {
-    SmallString<256> Res;
-    llvm::raw_svector_ostream OS(Res);
+    small_string_ostream<256> OS;
     OS << getSpelling();
     for (unsigned i = 0, e = getNumValues(); i != e; ++i) {
       if (i) OS << ',';
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index c2b739f..e28e1d1 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -1342,25 +1342,21 @@ printGenericOptionDiff(const Option &O, const GenericOptionValue &Value,
 
 // printOptionDiff - Specializations for printing basic value types.
 //
-#define PRINT_OPT_DIFF(T)                                               \
-  void parser<T>::                                                      \
-  printOptionDiff(const Option &O, T V, OptionValue<T> D,               \
-                  size_t GlobalWidth) const {                           \
-    printOptionName(O, GlobalWidth);                                    \
-    std::string Str;                                                    \
-    {                                                                   \
-      raw_string_ostream SS(Str);                                       \
-      SS << V;                                                          \
-    }                                                                   \
-    outs() << "= " << Str;                                              \
-    size_t NumSpaces = MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0;\
-    outs().indent(NumSpaces) << " (default: ";                          \
-    if (D.hasValue())                                                   \
-      outs() << D.getValue();                                           \
-    else                                                                \
-      outs() << "*no default*";                                         \
-    outs() << ")\n";                                                    \
-  }                                                                     \
+#define PRINT_OPT_DIFF(T)                                                      \
+  void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D,      \
+                                  size_t GlobalWidth) const {                  \
+    printOptionName(O, GlobalWidth);                                           \
+    string_ostream SS;                                                         \
+    SS << V;                                                                   \
+    outs() << "= " << SS.str();                                                \
+    size_t NumSpaces = MaxOptWidth > SS.tell() ? MaxOptWidth - SS.tell() : 0;  \
+    outs().indent(NumSpaces) << " (default: ";                                 \
+    if (D.hasValue())                                                          \
+      outs() << D.getValue();                                                  \
+    else                                                                       \
+      outs() << "*no default*";                                                \
+    outs() << ")\n";                                                           \
+  }
 
 PRINT_OPT_DIFF(bool)
 PRINT_OPT_DIFF(boolOrDefault)
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index f7c213a..6b95862 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -704,11 +704,15 @@ void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
 // and we only need to set the vector size when the data is flushed.
 
 raw_svector_ostream::raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {
+  init();
+}
+
+void raw_svector_ostream::init() {
   // Set up the initial external buffer. We make sure that the buffer has at
   // least 128 bytes free; raw_ostream itself only requires 64, but we want to
   // make sure that we don't grow the buffer unnecessarily on destruction (when
   // the data is flushed). See the FIXME below.
-  OS.reserve(OS.size() + 128);
+  OS.reserve(OS.size() + MinBuffer);
   SetBuffer(OS.end(), OS.capacity() - OS.size());
 }
 
@@ -723,7 +727,7 @@ raw_svector_ostream::~raw_svector_ostream() {
 void raw_svector_ostream::resync() {
   assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector");
 
-  if (OS.capacity() - OS.size() < 64)
+  if (OS.capacity() - OS.size() < MinBuffer / 2)
     OS.reserve(OS.capacity() * 2);
   SetBuffer(OS.end(), OS.capacity() - OS.size());
 }
@@ -743,7 +747,7 @@ void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
   }
 
   // Grow the vector if necessary.
-  if (OS.capacity() - OS.size() < 64)
+  if (OS.capacity() - OS.size() < MinBuffer / 2)
     OS.reserve(OS.capacity() * 2);
 
   // Update the buffer position.
diff --git a/lib/TableGen/SetTheory.cpp b/lib/TableGen/SetTheory.cpp
index c99c2ba..594d4d9 100644
--- a/lib/TableGen/SetTheory.cpp
+++ b/lib/TableGen/SetTheory.cpp
@@ -209,13 +209,12 @@ struct SequenceOp : public SetTheory::Operator {
         break;
       else if (Step < 0 && From < To)
         break;
-      std::string Name;
-      raw_string_ostream OS(Name);
-      OS << format(Format.c_str(), unsigned(From));
-      Record *Rec = Records.getDef(OS.str());
+      string_ostream Name;
+      Name << format(Format.c_str(), unsigned(From));
+      Record *Rec = Records.getDef(Name.str());
       if (!Rec)
-        PrintFatalError(Loc, "No def named '" + Name + "': " +
-          Expr->getAsString());
+        PrintFatalError(Loc, "No def named '" + Name.str() + "': " +
+                                 Expr->getAsString());
       // Try to reevaluate Rec in case it is a set.
       if (const RecVec *Result = ST.expand(Rec))
         Elts.insert(Result->begin(), Result->end());
diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp
index 0550692..76ef696 100644
--- a/lib/TableGen/TGParser.cpp
+++ b/lib/TableGen/TGParser.cpp
@@ -1307,8 +1307,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
     if (ItemType) {
       ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);
       if (!ListType) {
-        std::string s;
-        raw_string_ostream ss(s);
+        string_ostream ss;
         ss << "Type mismatch for list, expected list type, got "
            << ItemType->getAsString();
         TokError(ss.str());
diff --git a/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
index decf02a..b7f668e 100644
--- a/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
+++ b/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
@@ -146,8 +146,7 @@ const MCExpr *nvptx::LowerConstant(const Constant *CV, AsmPrinter &AP) {
 
     // Otherwise report the problem to the user.
     {
-      std::string S;
-      raw_string_ostream OS(S);
+      string_ostream OS;
       OS << "Unsupported expression in static initializer: ";
       CE->printAsOperand(OS, /*PrintType=*/ false,
                          !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
diff --git a/lib/Target/TargetMachineC.cpp b/lib/Target/TargetMachineC.cpp
index 20923c9..0b0a09a 100644
--- a/lib/Target/TargetMachineC.cpp
+++ b/lib/Target/TargetMachineC.cpp
@@ -237,15 +237,13 @@ LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
 LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
   LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
   LLVMMemoryBufferRef *OutMemBuf) {
-  std::string CodeString;
-  raw_string_ostream OStream(CodeString);
-  formatted_raw_ostream Out(OStream);
+  string_ostream Code;
+  formatted_raw_ostream Out(Code);
   bool Result = LLVMTargetMachineEmit(T, M, Out, codegen, ErrorMessage);
-  OStream.flush();
 
-  std::string &Data = OStream.str();
-  *OutMemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.c_str(),
-                                                     Data.length(), "");
+  StringRef Buffer = Code.str();
+  *OutMemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(Buffer.data(),
+                                                         Buffer.size(), "");
   return Result;
 }
 
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 3e57914..7e04608 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -2412,8 +2412,7 @@ bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     if (Match3 == Match_Success) MatchChars[NumMatches++] = Suffixes[2];
     if (Match4 == Match_Success) MatchChars[NumMatches++] = Suffixes[3];
 
-    SmallString<126> Msg;
-    raw_svector_ostream OS(Msg);
+    small_string_ostream<128> OS;
     OS << "ambiguous instructions require an explicit suffix (could be ";
     for (unsigned i = 0; i != NumMatches; ++i) {
       if (i != 0)
diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 7840342..3f9eb07 100644
--- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -281,8 +281,7 @@ void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
   unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
 
   if (RelaxedOp == Inst.getOpcode()) {
-    SmallString<256> Tmp;
-    raw_svector_ostream OS(Tmp);
+    small_string_ostream<256> OS;
     Inst.dump_pretty(OS);
     OS << "\n";
     report_fatal_error("unexpected instruction to relax: " + OS.str());
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 1dca568..cdfff82 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -550,8 +550,7 @@ emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
 }
 
 void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) {
-  SmallString<128> Directive;
-  raw_svector_ostream OS(Directive);
+  small_string_ostream<128> OS;
   StringRef Name = Sym->getName();
 
   if (Subtarget->isTargetKnownWindowsMSVC())
@@ -572,8 +571,7 @@ void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) {
       OS << ",data";
   }
 
-  OS.flush();
-  OutStreamer.EmitBytes(Directive);
+  OutStreamer.EmitBytes(OS.str());
 }
 
 void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp
index e98d4f9..7b5da33 100644
--- a/lib/Target/XCore/XCoreAsmPrinter.cpp
+++ b/lib/Target/XCore/XCoreAsmPrinter.cpp
@@ -267,8 +267,7 @@ PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
 }
 
 void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
-  SmallString<128> Str;
-  raw_svector_ostream O(Str);
+  small_string_ostream<128> O;
 
   switch (MI->getOpcode()) {
   case XCore::DBG_VALUE:
diff --git a/lib/Transforms/Instrumentation/DebugIR.cpp b/lib/Transforms/Instrumentation/DebugIR.cpp
index f2f1738..56e60e6 100644
--- a/lib/Transforms/Instrumentation/DebugIR.cpp
+++ b/lib/Transforms/Instrumentation/DebugIR.cpp
@@ -352,14 +352,12 @@ private:
   }
 
   std::string getTypeName(Type *T) {
-    std::string TypeName;
-    raw_string_ostream TypeStream(TypeName);
+    string_ostream OS;
     if (T)
-      T->print(TypeStream);
+      T->print(OS);
     else
-      TypeStream << "Printing <null> Type";
-    TypeStream.flush();
-    return TypeName;
+      OS << "Printing <null> Type";
+    return OS.str();
   }
 
   /// Returns the MDNode that represents type T if it is already created, or 0
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index cfeb62e..5af938b 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -316,11 +316,9 @@ namespace {
       }
       ReturnBlock = new GCOVBlock(i++, os);
 
-      std::string FunctionNameAndLine;
-      raw_string_ostream FNLOS(FunctionNameAndLine);
-      FNLOS << getFunctionName(SP) << SP.getLineNumber();
-      FNLOS.flush();
-      FuncChecksum = hash_value(FunctionNameAndLine);
+      string_ostream FnNameLine;
+      FnNameLine << getFunctionName(SP) << SP.getLineNumber();
+      FuncChecksum = hash_value(FnNameLine.str());
     }
 
     ~GCOVFunction() {
@@ -337,15 +335,14 @@ namespace {
     }
 
     std::string getEdgeDestinations() {
-      std::string EdgeDestinations;
-      raw_string_ostream EDOS(EdgeDestinations);
+      string_ostream EdgeDestinations;
       Function *F = Blocks.begin()->first->getParent();
       for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
         GCOVBlock &Block = *Blocks[I];
         for (int i = 0, e = Block.OutEdges.size(); i != e; ++i)
-          EDOS << Block.OutEdges[i]->Number;
+          EdgeDestinations << Block.OutEdges[i]->Number;
       }
-      return EdgeDestinations;
+      return EdgeDestinations.str();
     }
 
     uint32_t getFuncChecksum() {
diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index b08a477..1ec3142 100644
--- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2418,8 +2418,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
     if (PoisonStack && MS.TrackOrigins) {
       setOrigin(&I, getCleanOrigin());
-      SmallString<2048> StackDescriptionStorage;
-      raw_svector_ostream StackDescription(StackDescriptionStorage);
+      small_string_ostream<2048> StackDescription;
       // We create a string with a description of the stack allocation and
       // pass it into __msan_set_alloca_origin.
       // It will be printed by the run-time if stack-originated UMR is found.
diff --git a/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index dd4dd50..744fb24 100644
--- a/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -835,8 +835,7 @@ static MDString *AppendMDNodeToSourcePtr(unsigned NodeId,
       // of line at the module level and to provide a very simple format
       // encoding the information herein. Both of these makes it simpler to
       // parse the annotations by a simple external program.
-      std::string Str;
-      raw_string_ostream os(Str);
+      string_ostream os;
       os << "(" << Inst->getParent()->getParent()->getName() << ",%"
          << Inst->getName() << ")";
 
@@ -849,8 +848,7 @@ static MDString *AppendMDNodeToSourcePtr(unsigned NodeId,
       Hash = cast<MDString>(Node->getOperand(0));
     }
   } else if (Argument *Arg = dyn_cast<Argument>(Ptr)) {
-    std::string str;
-    raw_string_ostream os(str);
+    string_ostream os;
     os << "(" << Arg->getParent()->getName() << ",%" << Arg->getName()
        << ")";
     Hash = MDString::get(Arg->getContext(), os.str());
@@ -860,8 +858,7 @@ static MDString *AppendMDNodeToSourcePtr(unsigned NodeId,
 }
 
 static std::string SequenceToString(Sequence A) {
-  std::string str;
-  raw_string_ostream os(str);
+  string_ostream os;
   os << A;
   return os.str();
 }
diff --git a/lib/Transforms/Utils/ASanStackFrameLayout.cpp b/lib/Transforms/Utils/ASanStackFrameLayout.cpp
index cce016a..42fd398 100644
--- a/lib/Transforms/Utils/ASanStackFrameLayout.cpp
+++ b/lib/Transforms/Utils/ASanStackFrameLayout.cpp
@@ -65,8 +65,7 @@ ComputeASanStackFrameLayout(SmallVectorImpl<ASanStackVariableDescription> &Vars,
     Vars[i].Alignment = std::max(Vars[i].Alignment, kMinAlignment);
 
   std::stable_sort(Vars.begin(), Vars.end(), CompareVars);
-  SmallString<2048> StackDescriptionStorage;
-  raw_svector_ostream StackDescription(StackDescriptionStorage);
+  small_string_ostream<2048> StackDescription;
   StackDescription << NumVars;
   Layout->FrameAlignment = std::max(Granularity, Vars[0].Alignment);
   SmallVector<uint8_t, 64> &SB(Layout->ShadowBytes);
diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp
index cb8a41d..2338d29 100644
--- a/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -212,24 +212,23 @@ class LoopVectorizationCostModel;
 /// Optimization analysis message produced during vectorization. Messages inform
 /// the user why vectorization did not occur.
 class Report {
-  std::string Message;
-  raw_string_ostream Out;
+  string_ostream Message;
   Instruction *Instr;
 
 public:
-  Report(Instruction *I = nullptr) : Out(Message), Instr(I) {
-    Out << "loop not vectorized: ";
+  Report(Instruction *I = nullptr) : Instr(I) {
+    Message << "loop not vectorized: ";
   }
 
   template <typename A> Report &operator<<(const A &Value) {
-    Out << Value;
+    Message << Value;
     return *this;
   }
 
   Instruction *getInstr() { return Instr; }
 
-  std::string &str() { return Out.str(); }
-  operator Twine() { return Out.str(); }
+  StringRef str() { return Message.str(); }
+  operator Twine() { return Message.str(); }
 };
 
 /// InnerLoopVectorizer vectorizes loops which contain only one basic
@@ -503,18 +502,17 @@ static void setDebugLocFromInst(IRBuilder<> &B, const Value *Ptr) {
 #ifndef NDEBUG
 /// \return string containing a file name and a line # for the given loop.
 static std::string getDebugLocString(const Loop *L) {
-  std::string Result;
-  if (L) {
-    raw_string_ostream OS(Result);
-    const DebugLoc LoopDbgLoc = L->getStartLoc();
-    if (!LoopDbgLoc.isUnknown())
-      LoopDbgLoc.print(L->getHeader()->getContext(), OS);
-    else
-      // Just print the module name.
-      OS << L->getHeader()->getParent()->getParent()->getModuleIdentifier();
-    OS.flush();
-  }
-  return Result;
+  if (!L)
+    return std::string();
+
+  string_ostream OS;
+  const DebugLoc LoopDbgLoc = L->getStartLoc();
+  if (!LoopDbgLoc.isUnknown())
+    LoopDbgLoc.print(L->getHeader()->getContext(), OS);
+  else
+    // Just print the module name.
+    OS << L->getHeader()->getParent()->getParent()->getModuleIdentifier();
+  return OS.str();
 }
 #endif
 
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index 60886bb..2d7e8df 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -689,8 +689,7 @@ writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
                  std::vector<std::pair<unsigned, unsigned>> &MemberOffsetRefs) {
   unsigned StartOffset = 0;
   unsigned MemberNum = 0;
-  std::string NameBuf;
-  raw_string_ostream NameOS(NameBuf);
+  string_ostream NameOS;
   unsigned NumSyms = 0;
   LLVMContext &Context = getGlobalContext();
   for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index d98691b..d9886c1 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -222,8 +222,7 @@ static void emitDOTFile(const char *FileName, const MCFunction &f,
         Out << "<o>";
 
       // Escape special chars and print the instruction in mnemonic form.
-      std::string Str;
-      raw_string_ostream OS(Str);
+      string_ostream OS;
       IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, "");
       Out << DOT::EscapeString(OS.str());
     }
@@ -473,9 +472,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
     if (Symbols.empty())
       Symbols.push_back(std::make_pair(0, name));
 
-
-    SmallString<40> Comments;
-    raw_svector_ostream CommentStream(Comments);
+    small_string_ostream<40> Comments;
 
     StringRef Bytes;
     if (error(Section.getContents(Bytes)))
@@ -513,15 +510,14 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
         MCInst Inst;
 
         if (DisAsm->getInstruction(Inst, Size, memoryObject,
-                                   SectionAddr + Index,
-                                   DebugOut, CommentStream)) {
+                                   SectionAddr + Index, DebugOut, Comments)) {
           outs() << format("%8" PRIx64 ":", SectionAddr + Index);
           if (!NoShowRawInsn) {
             outs() << "\t";
             DumpBytes(StringRef(Bytes.data() + Index, Size));
           }
           IP->printInst(&Inst, outs(), "");
-          outs() << CommentStream.str();
+          outs() << Comments.str();
           Comments.clear();
           outs() << "\n";
         } else {
diff --git a/tools/llvm-readobj/ARMWinEHPrinter.cpp b/tools/llvm-readobj/ARMWinEHPrinter.cpp
index f6675bd..7138438 100644
--- a/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -95,8 +95,7 @@ raw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {
 
 static std::string formatSymbol(StringRef Name, uint64_t Address,
                                 uint64_t Offset = 0) {
-  std::string Buffer;
-  raw_string_ostream OS(Buffer);
+  string_ostream OS;
 
   if (!Name.empty())
     OS << Name << " ";
diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp
index f058632..2d67843 100644
--- a/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/tools/llvm-readobj/Win64EHDumper.cpp
@@ -115,8 +115,7 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
 static std::string formatSymbol(const Dumper::Context &Ctx,
                                 const coff_section *Section, uint64_t Offset,
                                 uint32_t Displacement) {
-  std::string Buffer;
-  raw_string_ostream OS(Buffer);
+  string_ostream OS;
 
   StringRef Name;
   SymbolRef Symbol;
@@ -131,6 +130,7 @@ static std::string formatSymbol(const Dumper::Context &Ctx,
     OS << format(" +0x%X (0x%" PRIX64 ")", Displacement, Offset);
   else
     OS << format(" (0x%" PRIX64 ")", Offset);
+
   return OS.str();
 }
 
diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp
index 817d207..aa79bdc 100644
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITTest.cpp
@@ -70,9 +70,9 @@ Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
 }
 
 std::string DumpFunction(const Function *F) {
-  std::string Result;
-  raw_string_ostream(Result) << "" << *F;
-  return Result;
+  string_ostream Result;
+  Result << "" << *F;
+  return Result.str();
 }
 
 class RecordingJITMemoryManager : public JITMemoryManager {
@@ -170,10 +170,9 @@ bool LoadAssemblyInto(Module *M, const char *assembly) {
   SMDiagnostic Error;
   bool success =
     nullptr != ParseAssemblyString(assembly, M, Error, M->getContext());
-  std::string errMsg;
-  raw_string_ostream os(errMsg);
-  Error.print("", os);
-  EXPECT_TRUE(success) << os.str();
+  string_ostream errMsg;
+  Error.print("", errMsg);
+  EXPECT_TRUE(success) << errMsg.str();
   return success;
 }
 
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 978e05f..2c33e68 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -458,8 +458,7 @@ void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
   // variable values.
   if (!VariableUses.empty()) {
     for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
-      SmallString<256> Msg;
-      raw_svector_ostream OS(Msg);
+      small_string_ostream<256> OS;
       StringRef Var = VariableUses[i].first;
       if (Var[0] == '@') {
         std::string Value;
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 4d0c0ca..5e27d45 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -319,8 +319,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
 
   // Default case: unhandled opcode
   o << "  default:\n"
-    << "    std::string msg;\n"
-    << "    raw_string_ostream Msg(msg);\n"
+    << "    string_ostream Msg;\n"
     << "    Msg << \"Not supported instr: \" << MI;\n"
     << "    report_fatal_error(Msg.str());\n"
     << "  }\n"
diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp
index 39b8f72..c3c7c15 100644
--- a/utils/yaml-bench/YAMLBench.cpp
+++ b/utils/yaml-bench/YAMLBench.cpp
@@ -166,23 +166,21 @@ static void benchmark( llvm::TimerGroup &Group
 }
 
 static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
-  std::string JSONText;
-  llvm::raw_string_ostream Stream(JSONText);
-  Stream << "[\n";
+  llvm::string_ostream OS;
+  OS << "[\n";
   size_t MemoryBytes = MemoryMB * 1024 * 1024;
-  while (JSONText.size() < MemoryBytes) {
-    Stream << " {\n"
-           << "  \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
-           << "  \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
-           << "  \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
-           << " }";
-    Stream.flush();
-    if (JSONText.size() < MemoryBytes) Stream << ",";
-    Stream << "\n";
+  while (OS.tell() < MemoryBytes) {
+    OS << " {\n"
+       << "  \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
+       << "  \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
+       << "  \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
+       << " }";
+    if (OS.tell() < MemoryBytes)
+      OS << ",";
+    OS << "\n";
   }
-  Stream << "]\n";
-  Stream.flush();
-  return JSONText;
+  OS << "]\n";
+  return OS.str();
 }
 
 int main(int argc, char **argv) {


More information about the llvm-commits mailing list