LLVM: lib/CodeGen/BasicBlockSectionsProfileReader.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

30

31using namespace llvm;

32

35 "bbsections-profile-reader",

36 "Reads and parses a basic block sections profile.", false,

37 false)

38

42 S.split(Parts, '.');

43 if (Parts.size() > 2)

44 return createProfileParseError(Twine("unable to parse basic block id: '") +

45 S + "'");

46 unsigned long long BaseBBID;

48 return createProfileParseError(

49 Twine("unable to parse BB id: '" + Parts[0]) +

50 "': unsigned integer expected");

51 unsigned long long CloneID = 0;

53 return createProfileParseError(Twine("unable to parse clone id: '") +

54 Parts[1] + "': unsigned integer expected");

55 return UniqueBBID{static_cast<unsigned>(BaseBBID),

56 static_cast<unsigned>(CloneID)};

57}

58

61}

62

63std::pair<bool, SmallVector>

66 auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));

67 return R != ProgramPathAndClusterInfo.end()

68 ? std::pair(true, R->second.ClusterInfo)

70}

71

75 return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;

76}

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133Error BasicBlockSectionsProfileReader::ReadV1Profile() {

134 auto FI = ProgramPathAndClusterInfo.end();

135

136

137 unsigned CurrentCluster = 0;

138

139 unsigned CurrentPosition = 0;

140

141

142

144

145

146

148

149 for (; !LineIt.is_at_eof(); ++LineIt) {

151 char Specifier = S[0];

152 S = S.drop_front().trim();

154 S.split(Values, ' ');

155 switch (Specifier) {

156 case '@':

157 continue;

158 case 'm':

159 if (Values.size() != 1) {

160 return createProfileParseError(Twine("invalid module name value: '") +

161 S + "'");

162 }

164 continue;

165 case 'f': {

166 bool FunctionFound = any_of(Values, [&](StringRef Alias) {

167 auto It = FunctionNameToDIFilename.find(Alias);

168

169 if (It == FunctionNameToDIFilename.end())

170 return false;

171

172

173 return DIFilename.empty() || It->second == DIFilename;

174 });

175 if (!FunctionFound) {

176

177

178 FI = ProgramPathAndClusterInfo.end();

179 DIFilename = "";

180 continue;

181 }

182 for (size_t i = 1; i < Values.size(); ++i)

183 FuncAliasMap.try_emplace(Values[i], Values.front());

184

185

186

187 auto R = ProgramPathAndClusterInfo.try_emplace(Values.front());

188

189

190 if (R.second)

191 return createProfileParseError("duplicate profile for function '" +

192 Values.front() + "'");

193 FI = R.first;

194 CurrentCluster = 0;

195 FuncBBIDs.clear();

196

197

198 DIFilename = "";

199 continue;

200 }

201 case 'c':

202

203

204 if (FI == ProgramPathAndClusterInfo.end())

205 continue;

206

207 CurrentPosition = 0;

208 for (auto BasicBlockIDStr : Values) {

209 auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr);

210 if (!BasicBlockID)

211 return BasicBlockID.takeError();

212 if (!FuncBBIDs.insert(*BasicBlockID).second)

213 return createProfileParseError(

214 Twine("duplicate basic block id found '") + BasicBlockIDStr +

215 "'");

216

217 FI->second.ClusterInfo.emplace_back(BBClusterInfo{

218 *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});

219 }

220 CurrentCluster++;

221 continue;

222 case 'p': {

223

224

225 if (FI == ProgramPathAndClusterInfo.end())

226 continue;

228 FI->second.ClonePaths.push_back({});

229 for (size_t I = 0; I < Values.size(); ++I) {

230 auto BaseBBIDStr = Values[I];

231 unsigned long long BaseBBID = 0;

233 return createProfileParseError(Twine("unsigned integer expected: '") +

234 BaseBBIDStr + "'");

235 if (I != 0 && !BBsInPath.insert(BaseBBID).second)

236 return createProfileParseError(

237 Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");

238 FI->second.ClonePaths.back().push_back(BaseBBID);

239 }

240 continue;

241 }

242 default:

243 return createProfileParseError(Twine("invalid specifier: '") +

244 Twine(Specifier) + "'");

245 }

246 llvm_unreachable("should not break from this switch statement");

247 }

249}

250

251Error BasicBlockSectionsProfileReader::ReadV0Profile() {

252 auto FI = ProgramPathAndClusterInfo.end();

253

254 unsigned CurrentCluster = 0;

255

256 unsigned CurrentPosition = 0;

257

258

259

261

262 for (; !LineIt.is_at_eof(); ++LineIt) {

264 if (S[0] == '@')

265 continue;

266

267 if (!S.consume_front("!") || S.empty())

268 break;

269

270 if (S.consume_front("!")) {

271

272

273 if (FI == ProgramPathAndClusterInfo.end())

274 continue;

276 S.split(BBIDs, ' ');

277

278 CurrentPosition = 0;

279 for (auto BBIDStr : BBIDs) {

280 unsigned long long BBID;

282 return createProfileParseError(Twine("unsigned integer expected: '") +

283 BBIDStr + "'");

284 if (!FuncBBIDs.insert(BBID).second)

285 return createProfileParseError(

286 Twine("duplicate basic block id found '") + BBIDStr + "'");

287

288 FI->second.ClusterInfo.emplace_back(

290 CurrentCluster,

291 CurrentPosition++}));

292 }

293 CurrentCluster++;

294 } else {

295

296

297 auto [AliasesStr, DIFilenameStr] = S.split(' ');

299 if (DIFilenameStr.starts_with("M=")) {

300 DIFilename =

302 if (DIFilename.empty())

303 return createProfileParseError("empty module name specifier");

304 } else if (!DIFilenameStr.empty()) {

305 return createProfileParseError("unknown string found: '" +

306 DIFilenameStr + "'");

307 }

308

309

310

312 AliasesStr.split(Aliases, '/');

313 bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {

314 auto It = FunctionNameToDIFilename.find(Alias);

315

316 if (It == FunctionNameToDIFilename.end())

317 return false;

318

319

320 return DIFilename.empty() || It->second == DIFilename;

321 });

322 if (!FunctionFound) {

323

324

325 FI = ProgramPathAndClusterInfo.end();

326 continue;

327 }

328 for (size_t i = 1; i < Aliases.size(); ++i)

329 FuncAliasMap.try_emplace(Aliases[i], Aliases.front());

330

331

332

333 auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());

334

335

336 if (R.second)

337 return createProfileParseError("duplicate profile for function '" +

338 Aliases.front() + "'");

339 FI = R.first;

340 CurrentCluster = 0;

341 FuncBBIDs.clear();

342 }

343 }

345}

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364Error BasicBlockSectionsProfileReader::ReadProfile() {

366

367 unsigned long long Version = 0;

369 if (FirstLine.consume_front("v")) {

371 return createProfileParseError(Twine("version number expected: '") +

372 FirstLine + "'");

373 }

375 return createProfileParseError(Twine("invalid profile version: ") +

377 }

378 ++LineIt;

379 }

380

382 case 0:

383

384 return ReadV0Profile();

385 case 1:

386 return ReadV1Profile();

387 default:

389 }

390}

391

394 return false;

395

396 BBSPR.FunctionNameToDIFilename.clear();

399 if (F.isDeclaration())

400 continue;

402 if (Subprogram) {

404 if (CU)

406 }

407 [[maybe_unused]] bool inserted =

408 BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename)

409 .second;

411 }

412 if (auto Err = BBSPR.ReadProfile())

414 return false;

415}

416

418

423}

424

428}

429

430std::pair<bool, SmallVector>

434}

435

440}

441

445}

446

450}

This file defines the StringMap class.

This file defines the DenseSet and SmallDenseSet classes.

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallSet class.

This file defines the SmallString class.

This file defines the SmallVector class.

A container for analyses that lazily runs them and caches their results.

Result run(Function &F, FunctionAnalysisManager &AM)

bool doInitialization(Module &M) override

doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...

BasicBlockSectionsProfileReader BBSPR

BasicBlockSectionsProfileReader & getBBSPR()

SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const

bool isFunctionHot(StringRef FuncName) const

std::pair< bool, SmallVector< BBClusterInfo > > getClusterInfoForFunction(StringRef FuncName) const

bool isFunctionHot(StringRef FuncName) const

std::pair< bool, SmallVector< BBClusterInfo > > getClusterInfoForFunction(StringRef FuncName) const

SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const

Implements a dense probed hash-table based set.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

ImmutablePass class - This class is used to provide information that does not need to be run.

This interface provides simple read-only access to a block of memory, and provides simple methods for...

A Module instance is used to store all the information related to an LLVM module.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

constexpr bool empty() const

empty - Check if the string is empty.

const MemoryBuffer * getBBSectionsFuncListBuf() const

Get the list of functions and basic block ids that need unique sections.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

std::pair< iterator, bool > insert(const ValueT &V)

bool is_at_eof() const

Return true if we've reached EOF or are an "end" iterator.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

StringRef remove_leading_dotslash(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Remove redundant leading "./" pieces and consecutive separators.

This is an optimization pass for GlobalISel generic memory operations.

ImmutablePass * createBasicBlockSectionsProfileReaderWrapperPass(const MemoryBuffer *Buf)

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

bool getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result)

Helper functions for StringRef::getAsInteger.

Implement std::hash so that hash_code can be used in STL containers.

A special type used by analysis passes to provide an address that identifies that particular analysis...