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