Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 1 | //===------------------ llvm-opt-report/OptReport.cpp ---------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 10 | /// This file implements a tool that can parse the YAML optimization |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 11 | /// records and generate an optimization summary annotated source listing |
| 12 | /// report. |
| 13 | /// |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
Francis Visoiu Mistrih | 1c4bab3 | 2019-03-05 20:45:17 +0000 | [diff] [blame] | 16 | #include "llvm-c/Remarks.h" |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 17 | #include "llvm/Demangle/Demangle.h" |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 18 | #include "llvm/Remarks/RemarkParser.h" |
Rui Ueyama | 197194b | 2018-04-13 18:26:06 +0000 | [diff] [blame] | 19 | #include "llvm/Support/CommandLine.h" |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 20 | #include "llvm/Support/Error.h" |
| 21 | #include "llvm/Support/ErrorOr.h" |
| 22 | #include "llvm/Support/FileSystem.h" |
| 23 | #include "llvm/Support/Format.h" |
Rui Ueyama | 197194b | 2018-04-13 18:26:06 +0000 | [diff] [blame] | 24 | #include "llvm/Support/InitLLVM.h" |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 25 | #include "llvm/Support/LineIterator.h" |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 26 | #include "llvm/Support/MemoryBuffer.h" |
| 27 | #include "llvm/Support/Path.h" |
| 28 | #include "llvm/Support/Program.h" |
Jonas Devlieghere | 2cd41eb | 2018-04-21 21:11:59 +0000 | [diff] [blame] | 29 | #include "llvm/Support/WithColor.h" |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 30 | #include "llvm/Support/YAMLTraits.h" |
Rui Ueyama | 197194b | 2018-04-13 18:26:06 +0000 | [diff] [blame] | 31 | #include "llvm/Support/raw_ostream.h" |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 32 | #include <cstdlib> |
| 33 | #include <map> |
| 34 | #include <set> |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 35 | |
| 36 | using namespace llvm; |
| 37 | using namespace llvm::yaml; |
| 38 | |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 39 | // Mark all our options with this category, everything else (except for -version |
| 40 | // and -help) will be hidden. |
| 41 | static cl::OptionCategory |
| 42 | OptReportCategory("llvm-opt-report options"); |
| 43 | |
| 44 | static cl::opt<std::string> |
| 45 | InputFileName(cl::Positional, cl::desc("<input>"), cl::init("-"), |
| 46 | cl::cat(OptReportCategory)); |
| 47 | |
| 48 | static cl::opt<std::string> |
| 49 | OutputFileName("o", cl::desc("Output file"), cl::init("-"), |
| 50 | cl::cat(OptReportCategory)); |
| 51 | |
| 52 | static cl::opt<std::string> |
| 53 | InputRelDir("r", cl::desc("Root for relative input paths"), cl::init(""), |
| 54 | cl::cat(OptReportCategory)); |
| 55 | |
| 56 | static cl::opt<bool> |
| 57 | Succinct("s", cl::desc("Don't include vectorization factors, etc."), |
| 58 | cl::init(false), cl::cat(OptReportCategory)); |
| 59 | |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 60 | static cl::opt<bool> |
Hal Finkel | 16d29e3 | 2016-10-07 01:30:59 +0000 | [diff] [blame] | 61 | NoDemangle("no-demangle", cl::desc("Don't demangle function names"), |
| 62 | cl::init(false), cl::cat(OptReportCategory)); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 63 | |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 64 | namespace { |
| 65 | // For each location in the source file, the common per-transformation state |
| 66 | // collected. |
| 67 | struct OptReportLocationItemInfo { |
| 68 | bool Analyzed = false; |
| 69 | bool Transformed = false; |
| 70 | |
| 71 | OptReportLocationItemInfo &operator |= ( |
| 72 | const OptReportLocationItemInfo &RHS) { |
| 73 | Analyzed |= RHS.Analyzed; |
| 74 | Transformed |= RHS.Transformed; |
| 75 | |
| 76 | return *this; |
| 77 | } |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 78 | |
| 79 | bool operator < (const OptReportLocationItemInfo &RHS) const { |
| 80 | if (Analyzed < RHS.Analyzed) |
| 81 | return true; |
| 82 | else if (Analyzed > RHS.Analyzed) |
| 83 | return false; |
| 84 | else if (Transformed < RHS.Transformed) |
| 85 | return true; |
| 86 | return false; |
| 87 | } |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 88 | }; |
| 89 | |
| 90 | // The per-location information collected for producing an optimization report. |
| 91 | struct OptReportLocationInfo { |
| 92 | OptReportLocationItemInfo Inlined; |
| 93 | OptReportLocationItemInfo Unrolled; |
| 94 | OptReportLocationItemInfo Vectorized; |
| 95 | |
| 96 | int VectorizationFactor = 1; |
| 97 | int InterleaveCount = 1; |
| 98 | int UnrollCount = 1; |
| 99 | |
| 100 | OptReportLocationInfo &operator |= (const OptReportLocationInfo &RHS) { |
| 101 | Inlined |= RHS.Inlined; |
| 102 | Unrolled |= RHS.Unrolled; |
| 103 | Vectorized |= RHS.Vectorized; |
| 104 | |
| 105 | VectorizationFactor = |
| 106 | std::max(VectorizationFactor, RHS.VectorizationFactor); |
| 107 | InterleaveCount = std::max(InterleaveCount, RHS.InterleaveCount); |
| 108 | UnrollCount = std::max(UnrollCount, RHS.UnrollCount); |
| 109 | |
| 110 | return *this; |
| 111 | } |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 112 | |
| 113 | bool operator < (const OptReportLocationInfo &RHS) const { |
| 114 | if (Inlined < RHS.Inlined) |
| 115 | return true; |
| 116 | else if (RHS.Inlined < Inlined) |
| 117 | return false; |
| 118 | else if (Unrolled < RHS.Unrolled) |
| 119 | return true; |
| 120 | else if (RHS.Unrolled < Unrolled) |
| 121 | return false; |
| 122 | else if (Vectorized < RHS.Vectorized) |
| 123 | return true; |
| 124 | else if (RHS.Vectorized < Vectorized || Succinct) |
| 125 | return false; |
| 126 | else if (VectorizationFactor < RHS.VectorizationFactor) |
| 127 | return true; |
| 128 | else if (VectorizationFactor > RHS.VectorizationFactor) |
| 129 | return false; |
| 130 | else if (InterleaveCount < RHS.InterleaveCount) |
| 131 | return true; |
| 132 | else if (InterleaveCount > RHS.InterleaveCount) |
| 133 | return false; |
Hal Finkel | fd44840 | 2016-10-24 05:07:18 +0000 | [diff] [blame] | 134 | else if (UnrollCount < RHS.UnrollCount) |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 135 | return true; |
| 136 | return false; |
| 137 | } |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 138 | }; |
| 139 | |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 140 | typedef std::map<std::string, std::map<int, std::map<std::string, std::map<int, |
| 141 | OptReportLocationInfo>>>> LocationInfoTy; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 142 | } // anonymous namespace |
| 143 | |
Francis Visoiu Mistrih | 2e76cab | 2018-10-10 18:43:42 +0000 | [diff] [blame] | 144 | static bool readLocationInfo(LocationInfoTy &LocationInfo) { |
| 145 | ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = |
| 146 | MemoryBuffer::getFile(InputFileName.c_str()); |
| 147 | if (std::error_code EC = Buf.getError()) { |
| 148 | WithColor::error() << "Can't open file " << InputFileName << ": " |
| 149 | << EC.message() << "\n"; |
| 150 | return false; |
| 151 | } |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 152 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 153 | remarks::Parser Parser((*Buf)->getBuffer()); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 154 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 155 | while (true) { |
| 156 | Expected<const remarks::Remark *> RemarkOrErr = Parser.getNext(); |
| 157 | if (!RemarkOrErr) { |
| 158 | handleAllErrors(RemarkOrErr.takeError(), [&](const ErrorInfoBase &PE) { |
| 159 | PE.log(WithColor::error()); |
| 160 | }); |
| 161 | return false; |
| 162 | } |
| 163 | if (!*RemarkOrErr) // End of file. |
| 164 | break; |
| 165 | |
| 166 | const remarks::Remark &Remark = **RemarkOrErr; |
| 167 | |
| 168 | bool Transformed = Remark.RemarkType == remarks::Type::Passed; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 169 | |
| 170 | int VectorizationFactor = 1; |
| 171 | int InterleaveCount = 1; |
| 172 | int UnrollCount = 1; |
| 173 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 174 | for (const remarks::Argument &Arg : Remark.Args) { |
| 175 | if (Arg.Key == "VectorizationFactor") |
| 176 | Arg.Val.getAsInteger(10, VectorizationFactor); |
| 177 | else if (Arg.Key == "InterleaveCount") |
| 178 | Arg.Val.getAsInteger(10, InterleaveCount); |
| 179 | else if (Arg.Key == "UnrollCount") |
| 180 | Arg.Val.getAsInteger(10, UnrollCount); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 181 | } |
| 182 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 183 | const Optional<remarks::RemarkLocation> &Loc = Remark.Loc; |
| 184 | if (!Loc) |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 185 | continue; |
| 186 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 187 | StringRef File = Loc->SourceFilePath; |
| 188 | unsigned Line = Loc->SourceLine; |
| 189 | unsigned Column = Loc->SourceColumn; |
| 190 | |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 191 | // We track information on both actual and potential transformations. This |
| 192 | // way, if there are multiple possible things on a line that are, or could |
| 193 | // have been transformed, we can indicate that explicitly in the output. |
Hal Finkel | 4d6f308 | 2016-10-06 11:58:52 +0000 | [diff] [blame] | 194 | auto UpdateLLII = [Transformed](OptReportLocationItemInfo &LLII) { |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 195 | LLII.Analyzed = true; |
Hal Finkel | 4d6f308 | 2016-10-06 11:58:52 +0000 | [diff] [blame] | 196 | if (Transformed) |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 197 | LLII.Transformed = true; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 198 | }; |
| 199 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 200 | if (Remark.PassName == "inline") { |
| 201 | auto &LI = LocationInfo[File][Line][Remark.FunctionName][Column]; |
Hal Finkel | 4d6f308 | 2016-10-06 11:58:52 +0000 | [diff] [blame] | 202 | UpdateLLII(LI.Inlined); |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 203 | } else if (Remark.PassName == "loop-unroll") { |
| 204 | auto &LI = LocationInfo[File][Line][Remark.FunctionName][Column]; |
Hal Finkel | 4d6f308 | 2016-10-06 11:58:52 +0000 | [diff] [blame] | 205 | LI.UnrollCount = UnrollCount; |
| 206 | UpdateLLII(LI.Unrolled); |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 207 | } else if (Remark.PassName == "loop-vectorize") { |
| 208 | auto &LI = LocationInfo[File][Line][Remark.FunctionName][Column]; |
Hal Finkel | 4d6f308 | 2016-10-06 11:58:52 +0000 | [diff] [blame] | 209 | LI.VectorizationFactor = VectorizationFactor; |
| 210 | LI.InterleaveCount = InterleaveCount; |
| 211 | UpdateLLII(LI.Vectorized); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 212 | } |
| 213 | } |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 214 | |
Francis Visoiu Mistrih | 5a05cc0 | 2019-03-19 21:11:07 +0000 | [diff] [blame] | 215 | return true; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | static bool writeReport(LocationInfoTy &LocationInfo) { |
| 219 | std::error_code EC; |
| 220 | llvm::raw_fd_ostream OS(OutputFileName, EC, |
| 221 | llvm::sys::fs::F_Text); |
| 222 | if (EC) { |
Jonas Devlieghere | 2cd41eb | 2018-04-21 21:11:59 +0000 | [diff] [blame] | 223 | WithColor::error() << "Can't open file " << OutputFileName << ": " |
| 224 | << EC.message() << "\n"; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 225 | return false; |
| 226 | } |
| 227 | |
| 228 | bool FirstFile = true; |
| 229 | for (auto &FI : LocationInfo) { |
| 230 | SmallString<128> FileName(FI.first); |
Pavel Labath | 1ad53ca | 2019-01-16 09:55:32 +0000 | [diff] [blame] | 231 | if (!InputRelDir.empty()) |
| 232 | sys::fs::make_absolute(InputRelDir, FileName); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 233 | |
| 234 | const auto &FileInfo = FI.second; |
| 235 | |
| 236 | ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = |
| 237 | MemoryBuffer::getFile(FileName); |
| 238 | if (std::error_code EC = Buf.getError()) { |
Jonas Devlieghere | 2cd41eb | 2018-04-21 21:11:59 +0000 | [diff] [blame] | 239 | WithColor::error() << "Can't open file " << FileName << ": " |
| 240 | << EC.message() << "\n"; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 241 | return false; |
| 242 | } |
| 243 | |
| 244 | if (FirstFile) |
| 245 | FirstFile = false; |
| 246 | else |
| 247 | OS << "\n"; |
| 248 | |
| 249 | OS << "< " << FileName << "\n"; |
| 250 | |
| 251 | // Figure out how many characters we need for the vectorization factors |
| 252 | // and similar. |
| 253 | OptReportLocationInfo MaxLI; |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 254 | for (auto &FLI : FileInfo) |
| 255 | for (auto &FI : FLI.second) |
| 256 | for (auto &LI : FI.second) |
| 257 | MaxLI |= LI.second; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 258 | |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 259 | bool NothingInlined = !MaxLI.Inlined.Transformed; |
| 260 | bool NothingUnrolled = !MaxLI.Unrolled.Transformed; |
| 261 | bool NothingVectorized = !MaxLI.Vectorized.Transformed; |
| 262 | |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 263 | unsigned VFDigits = llvm::utostr(MaxLI.VectorizationFactor).size(); |
| 264 | unsigned ICDigits = llvm::utostr(MaxLI.InterleaveCount).size(); |
| 265 | unsigned UCDigits = llvm::utostr(MaxLI.UnrollCount).size(); |
| 266 | |
| 267 | // Figure out how many characters we need for the line numbers. |
| 268 | int64_t NumLines = 0; |
| 269 | for (line_iterator LI(*Buf.get(), false); LI != line_iterator(); ++LI) |
| 270 | ++NumLines; |
| 271 | |
| 272 | unsigned LNDigits = llvm::utostr(NumLines).size(); |
| 273 | |
| 274 | for (line_iterator LI(*Buf.get(), false); LI != line_iterator(); ++LI) { |
| 275 | int64_t L = LI.line_number(); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 276 | auto LII = FileInfo.find(L); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 277 | |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 278 | auto PrintLine = [&](bool PrintFuncName, |
| 279 | const std::set<std::string> &FuncNameSet) { |
| 280 | OptReportLocationInfo LLI; |
| 281 | |
| 282 | std::map<int, OptReportLocationInfo> ColsInfo; |
| 283 | unsigned InlinedCols = 0, UnrolledCols = 0, VectorizedCols = 0; |
| 284 | |
Hal Finkel | ec85fc5 | 2017-01-07 20:21:17 +0000 | [diff] [blame] | 285 | if (LII != FileInfo.end() && !FuncNameSet.empty()) { |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 286 | const auto &LineInfo = LII->second; |
| 287 | |
| 288 | for (auto &CI : LineInfo.find(*FuncNameSet.begin())->second) { |
| 289 | int Col = CI.first; |
| 290 | ColsInfo[Col] = CI.second; |
| 291 | InlinedCols += CI.second.Inlined.Analyzed; |
| 292 | UnrolledCols += CI.second.Unrolled.Analyzed; |
| 293 | VectorizedCols += CI.second.Vectorized.Analyzed; |
| 294 | LLI |= CI.second; |
| 295 | } |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 296 | } |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 297 | |
| 298 | if (PrintFuncName) { |
| 299 | OS << " > "; |
| 300 | |
| 301 | bool FirstFunc = true; |
| 302 | for (const auto &FuncName : FuncNameSet) { |
| 303 | if (FirstFunc) |
| 304 | FirstFunc = false; |
| 305 | else |
| 306 | OS << ", "; |
| 307 | |
| 308 | bool Printed = false; |
Hal Finkel | 16d29e3 | 2016-10-07 01:30:59 +0000 | [diff] [blame] | 309 | if (!NoDemangle) { |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 310 | int Status = 0; |
| 311 | char *Demangled = |
| 312 | itaniumDemangle(FuncName.c_str(), nullptr, nullptr, &Status); |
| 313 | if (Demangled && Status == 0) { |
| 314 | OS << Demangled; |
| 315 | Printed = true; |
| 316 | } |
| 317 | |
| 318 | if (Demangled) |
| 319 | std::free(Demangled); |
| 320 | } |
| 321 | |
| 322 | if (!Printed) |
| 323 | OS << FuncName; |
Jonas Devlieghere | 2cd41eb | 2018-04-21 21:11:59 +0000 | [diff] [blame] | 324 | } |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 325 | |
| 326 | OS << ":\n"; |
| 327 | } |
| 328 | |
| 329 | // We try to keep the output as concise as possible. If only one thing on |
| 330 | // a given line could have been inlined, vectorized, etc. then we can put |
| 331 | // the marker on the source line itself. If there are multiple options |
| 332 | // then we want to distinguish them by placing the marker for each |
| 333 | // transformation on a separate line following the source line. When we |
| 334 | // do this, we use a '^' character to point to the appropriate column in |
| 335 | // the source line. |
| 336 | |
| 337 | std::string USpaces(Succinct ? 0 : UCDigits, ' '); |
| 338 | std::string VSpaces(Succinct ? 0 : VFDigits + ICDigits + 1, ' '); |
| 339 | |
| 340 | auto UStr = [UCDigits](OptReportLocationInfo &LLI) { |
| 341 | std::string R; |
| 342 | raw_string_ostream RS(R); |
Hal Finkel | 5d41f03 | 2016-10-07 02:01:03 +0000 | [diff] [blame] | 343 | |
| 344 | if (!Succinct) { |
| 345 | RS << LLI.UnrollCount; |
| 346 | RS << std::string(UCDigits - RS.str().size(), ' '); |
| 347 | } |
| 348 | |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 349 | return RS.str(); |
| 350 | }; |
| 351 | |
| 352 | auto VStr = [VFDigits, |
| 353 | ICDigits](OptReportLocationInfo &LLI) -> std::string { |
| 354 | std::string R; |
| 355 | raw_string_ostream RS(R); |
Hal Finkel | 5d41f03 | 2016-10-07 02:01:03 +0000 | [diff] [blame] | 356 | |
| 357 | if (!Succinct) { |
| 358 | RS << LLI.VectorizationFactor << "," << LLI.InterleaveCount; |
| 359 | RS << std::string(VFDigits + ICDigits + 1 - RS.str().size(), ' '); |
| 360 | } |
| 361 | |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 362 | return RS.str(); |
| 363 | }; |
| 364 | |
Hal Finkel | 47faf3b | 2016-10-06 11:11:11 +0000 | [diff] [blame] | 365 | OS << llvm::format_decimal(L, LNDigits) << " "; |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 366 | OS << (LLI.Inlined.Transformed && InlinedCols < 2 ? "I" : |
| 367 | (NothingInlined ? "" : " ")); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 368 | OS << (LLI.Unrolled.Transformed && UnrolledCols < 2 ? |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 369 | "U" + UStr(LLI) : (NothingUnrolled ? "" : " " + USpaces)); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 370 | OS << (LLI.Vectorized.Transformed && VectorizedCols < 2 ? |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 371 | "V" + VStr(LLI) : (NothingVectorized ? "" : " " + VSpaces)); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 372 | |
| 373 | OS << " | " << *LI << "\n"; |
| 374 | |
| 375 | for (auto &J : ColsInfo) { |
| 376 | if ((J.second.Inlined.Transformed && InlinedCols > 1) || |
| 377 | (J.second.Unrolled.Transformed && UnrolledCols > 1) || |
| 378 | (J.second.Vectorized.Transformed && VectorizedCols > 1)) { |
| 379 | OS << std::string(LNDigits + 1, ' '); |
| 380 | OS << (J.second.Inlined.Transformed && |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 381 | InlinedCols > 1 ? "I" : (NothingInlined ? "" : " ")); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 382 | OS << (J.second.Unrolled.Transformed && |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 383 | UnrolledCols > 1 ? "U" + UStr(J.second) : |
| 384 | (NothingUnrolled ? "" : " " + USpaces)); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 385 | OS << (J.second.Vectorized.Transformed && |
Hal Finkel | f495280 | 2016-10-08 00:26:54 +0000 | [diff] [blame] | 386 | VectorizedCols > 1 ? "V" + VStr(J.second) : |
| 387 | (NothingVectorized ? "" : " " + VSpaces)); |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 388 | |
| 389 | OS << " | " << std::string(J.first - 1, ' ') << "^\n"; |
| 390 | } |
| 391 | } |
| 392 | }; |
| 393 | |
| 394 | // We need to figure out if the optimizations for this line were the same |
| 395 | // in each function context. If not, then we want to group the similar |
| 396 | // function contexts together and display each group separately. If |
| 397 | // they're all the same, then we only display the line once without any |
| 398 | // additional markings. |
| 399 | std::map<std::map<int, OptReportLocationInfo>, |
| 400 | std::set<std::string>> UniqueLIs; |
| 401 | |
Hal Finkel | ec85fc5 | 2017-01-07 20:21:17 +0000 | [diff] [blame] | 402 | OptReportLocationInfo AllLI; |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 403 | if (LII != FileInfo.end()) { |
| 404 | const auto &FuncLineInfo = LII->second; |
Hal Finkel | ec85fc5 | 2017-01-07 20:21:17 +0000 | [diff] [blame] | 405 | for (const auto &FLII : FuncLineInfo) { |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 406 | UniqueLIs[FLII.second].insert(FLII.first); |
Hal Finkel | ec85fc5 | 2017-01-07 20:21:17 +0000 | [diff] [blame] | 407 | |
| 408 | for (const auto &OI : FLII.second) |
| 409 | AllLI |= OI.second; |
| 410 | } |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 411 | } |
| 412 | |
Hal Finkel | ec85fc5 | 2017-01-07 20:21:17 +0000 | [diff] [blame] | 413 | bool NothingHappened = !AllLI.Inlined.Transformed && |
| 414 | !AllLI.Unrolled.Transformed && |
| 415 | !AllLI.Vectorized.Transformed; |
| 416 | if (UniqueLIs.size() > 1 && !NothingHappened) { |
Hal Finkel | 5aa0248 | 2016-10-05 22:25:33 +0000 | [diff] [blame] | 417 | OS << " [[\n"; |
| 418 | for (const auto &FSLI : UniqueLIs) |
| 419 | PrintLine(true, FSLI.second); |
| 420 | OS << " ]]\n"; |
| 421 | } else if (UniqueLIs.size() == 1) { |
| 422 | PrintLine(false, UniqueLIs.begin()->second); |
| 423 | } else { |
| 424 | PrintLine(false, std::set<std::string>()); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 425 | } |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | return true; |
| 430 | } |
| 431 | |
| 432 | int main(int argc, const char **argv) { |
Rui Ueyama | 197194b | 2018-04-13 18:26:06 +0000 | [diff] [blame] | 433 | InitLLVM X(argc, argv); |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 434 | |
| 435 | cl::HideUnrelatedOptions(OptReportCategory); |
| 436 | cl::ParseCommandLineOptions( |
| 437 | argc, argv, |
| 438 | "A tool to generate an optimization report from YAML optimization" |
| 439 | " record files.\n"); |
| 440 | |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 441 | LocationInfoTy LocationInfo; |
| 442 | if (!readLocationInfo(LocationInfo)) |
| 443 | return 1; |
| 444 | if (!writeReport(LocationInfo)) |
Jonas Devlieghere | 2cd41eb | 2018-04-21 21:11:59 +0000 | [diff] [blame] | 445 | return 1; |
Hal Finkel | 52031b7 | 2016-10-05 22:10:35 +0000 | [diff] [blame] | 446 | |
| 447 | return 0; |
| 448 | } |