From 407b1e65a464081e28c325273b65e8eafdfad1d4 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 10 Jan 2021 14:32:02 -0800 Subject: [PATCH] [StringExtras] Add a helper class for comma-separated lists This patch introduces a helper class SubsequentDelim to simplify loops that generate a comma-separated lists. For example, consider the following loop, taken from llvm/lib/CodeGen/MachineBasicBlock.cpp: for (auto I = pred_begin(), E = pred_end(); I != E; ++I) { if (I != pred_begin()) OS << ", "; OS << printMBBReference(**I); } The new class allows us to rewrite the loop as: SubsequentDelim SD; for (auto I = pred_begin(), E = pred_end(); I != E; ++I) OS << SD << printMBBReference(**I); where SD evaluates to the empty string for the first time and ", " for subsequent iterations. Unlike interleaveComma, defined in llvm/include/llvm/ADT/STLExtras.h, SubsequentDelim can accommodate a wider variety of loops, including: - those that conditionally skip certain items, - those that need iterators to call getSuccProbability(I), and - those that iterate over integer ranges. As an example, this patch cleans up MachineBasicBlock::print. Differential Revision: https://reviews.llvm.org/D94377 --- llvm/include/llvm/ADT/StringExtras.h | 24 ++++++++++++++++++++++++ llvm/lib/CodeGen/MachineBasicBlock.cpp | 25 +++++++++---------------- llvm/unittests/ADT/StringExtrasTest.cpp | 14 ++++++++++++++ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h index 77288f8514dc..1fea700efe0c 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/include/llvm/ADT/StringExtras.h @@ -462,6 +462,30 @@ inline std::string join_items(Sep Separator, Args &&... Items) { return Result; } +/// A helper class to return the specified delimiter string after the first +/// invocation of operator StringRef(). Used to generate a comma-separated +/// list from a loop like so: +/// +/// \code +/// SubsequentDelim SD; +/// for (auto &I : C) +/// OS << SD << I.getName(); +/// \end +class SubsequentDelim { + bool First = true; + StringRef Delim; + + public: + SubsequentDelim(StringRef Delim = ", ") : Delim(Delim) {} + operator StringRef() { + if (First) { + First = false; + return {}; + } + return Delim; + } +}; + } // end namespace llvm #endif // LLVM_ADT_STRINGEXTRAS_H diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp index 14a270f994b4..c7b404e075e1 100644 --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -353,11 +353,9 @@ void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST, if (Indexes) OS << '\t'; // Don't indent(2), align with previous line attributes. OS << "; predecessors: "; - for (auto I = pred_begin(), E = pred_end(); I != E; ++I) { - if (I != pred_begin()) - OS << ", "; - OS << printMBBReference(**I); - } + SubsequentDelim SD; + for (auto *Pred : predecessors()) + OS << SD << printMBBReference(*Pred); OS << '\n'; HasLineAttributes = true; } @@ -366,10 +364,9 @@ void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST, if (Indexes) OS << '\t'; // Print the successors OS.indent(2) << "successors: "; + SubsequentDelim SD; for (auto I = succ_begin(), E = succ_end(); I != E; ++I) { - if (I != succ_begin()) - OS << ", "; - OS << printMBBReference(**I); + OS << SD << printMBBReference(**I); if (!Probs.empty()) OS << '(' << format("0x%08" PRIx32, getSuccProbability(I).getNumerator()) @@ -378,11 +375,10 @@ void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST, if (!Probs.empty() && IsStandalone) { // Print human readable probabilities as comments. OS << "; "; + SubsequentDelim SD; for (auto I = succ_begin(), E = succ_end(); I != E; ++I) { const BranchProbability &BP = getSuccProbability(I); - if (I != succ_begin()) - OS << ", "; - OS << printMBBReference(**I) << '(' + OS << SD << printMBBReference(**I) << '(' << format("%.2f%%", rint(((double)BP.getNumerator() / BP.getDenominator()) * 100.0 * 100.0) / @@ -399,12 +395,9 @@ void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST, if (Indexes) OS << '\t'; OS.indent(2) << "liveins: "; - bool First = true; + SubsequentDelim SD; for (const auto &LI : liveins()) { - if (!First) - OS << ", "; - First = false; - OS << printReg(LI.PhysReg, TRI); + OS << SD << printReg(LI.PhysReg, TRI); if (!LI.LaneMask.all()) OS << ":0x" << PrintLaneMask(LI.LaneMask); } diff --git a/llvm/unittests/ADT/StringExtrasTest.cpp b/llvm/unittests/ADT/StringExtrasTest.cpp index b785bb51844b..97a5f946a216 100644 --- a/llvm/unittests/ADT/StringExtrasTest.cpp +++ b/llvm/unittests/ADT/StringExtrasTest.cpp @@ -215,3 +215,17 @@ TEST(StringExtras, IToStr) { EXPECT_EQ(std::to_string(MinInt64), itostr(MinInt64)); EXPECT_EQ(std::to_string(MaxInt64), itostr(MaxInt64)); } + +TEST(StringExtras, SubsequentDelim) { + SubsequentDelim SD; + StringRef S = SD; + EXPECT_EQ(S, ""); + S = SD; + EXPECT_EQ(S, ", "); + + SubsequentDelim SD2(" "); + S = SD2; + EXPECT_EQ(S, ""); + S = SD2; + EXPECT_EQ(S, " "); +}