Skip to content

Commit a5dbf94

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:bbae59ae71c7 into amd-gfx:af6b7b051c01
Local branch amd-gfx af6b7b0 Merged main:2f1399c73f52 into amd-gfx:88b84f4b16eb Remote branch main bbae59a [clang-format] Finalize children after formatting them (llvm#73753)
2 parents af6b7b0 + bbae59a commit a5dbf94

File tree

66 files changed

+2232
-880
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2232
-880
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,9 @@ class BinaryContext {
611611
/// Indicates if the binary contains split functions.
612612
bool HasSplitFunctions{false};
613613

614+
/// Indicates if the function ordering of the binary is finalized.
615+
bool HasFinalizedFunctionOrder{false};
616+
614617
/// Is the binary always loaded at a fixed address. Shared objects and
615618
/// position-independent executables (PIEs) are examples of binaries that
616619
/// will have HasFixedLoadAddress set to false.

bolt/include/bolt/Passes/SplitFunctions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ enum SplitFunctionsStrategy : char {
2323
/// Split each function into a hot and cold fragment using profiling
2424
/// information.
2525
Profile2 = 0,
26+
/// Split each function into a hot, warm, and cold fragment using
27+
/// profiling information.
28+
CDSplit,
2629
/// Split each function into a hot and cold fragment at a randomly chosen
2730
/// split point (ignoring any available profiling information).
2831
Random2,
@@ -40,7 +43,7 @@ class SplitStrategy {
4043

4144
virtual ~SplitStrategy() = default;
4245
virtual bool canSplit(const BinaryFunction &BF) = 0;
43-
virtual bool keepEmpty() = 0;
46+
virtual bool compactFragments() = 0;
4447
virtual void fragment(const BlockIt Start, const BlockIt End) = 0;
4548
};
4649

bolt/lib/Passes/ReorderFunctions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
427427

428428
reorder(std::move(Clusters), BFs);
429429

430+
BC.HasFinalizedFunctionOrder = true;
431+
430432
std::unique_ptr<std::ofstream> FuncsFile;
431433
if (!opts::GenerateFunctionOrderFile.empty()) {
432434
FuncsFile = std::make_unique<std::ofstream>(opts::GenerateFunctionOrderFile,

bolt/lib/Passes/SplitFunctions.cpp

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ static cl::opt<SplitFunctionsStrategy> SplitStrategy(
9292
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
9393
"split each function into a hot and cold fragment "
9494
"using profiling information")),
95+
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
96+
"split each function into a hot, warm, and cold "
97+
"fragment using profiling information")),
9598
cl::values(clEnumValN(
9699
SplitFunctionsStrategy::Random2, "random2",
97100
"split each function into a hot and cold fragment at a randomly chosen "
@@ -126,7 +129,7 @@ struct SplitProfile2 final : public SplitStrategy {
126129
return BF.hasValidProfile() && hasFullProfile(BF) && !allBlocksCold(BF);
127130
}
128131

129-
bool keepEmpty() override { return false; }
132+
bool compactFragments() override { return true; }
130133

131134
void fragment(const BlockIt Start, const BlockIt End) override {
132135
for (BinaryBasicBlock *const BB : llvm::make_range(Start, End)) {
@@ -136,14 +139,59 @@ struct SplitProfile2 final : public SplitStrategy {
136139
}
137140
};
138141

142+
struct SplitCacheDirected final : public SplitStrategy {
143+
using BasicBlockOrder = BinaryFunction::BasicBlockOrderType;
144+
145+
bool canSplit(const BinaryFunction &BF) override {
146+
return BF.hasValidProfile() && hasFullProfile(BF) && !allBlocksCold(BF);
147+
}
148+
149+
// When some functions are hot-warm split and others are hot-warm-cold split,
150+
// we do not want to change the fragment numbers of the blocks in the hot-warm
151+
// split functions.
152+
bool compactFragments() override { return false; }
153+
154+
void fragment(const BlockIt Start, const BlockIt End) override {
155+
BasicBlockOrder BlockOrder(Start, End);
156+
BinaryFunction &BF = *BlockOrder.front()->getFunction();
157+
158+
size_t BestSplitIndex = findSplitIndex(BF, BlockOrder);
159+
160+
// Assign fragments based on the computed best split index.
161+
// All basic blocks with index up to the best split index become hot.
162+
// All remaining blocks are warm / cold depending on if count is
163+
// greater than 0 or not.
164+
FragmentNum Main(0);
165+
FragmentNum Cold(1);
166+
FragmentNum Warm(2);
167+
for (size_t Index = 0; Index < BlockOrder.size(); Index++) {
168+
BinaryBasicBlock *BB = BlockOrder[Index];
169+
if (Index <= BestSplitIndex)
170+
BB->setFragmentNum(Main);
171+
else
172+
BB->setFragmentNum(BB->getKnownExecutionCount() > 0 ? Warm : Cold);
173+
}
174+
}
175+
176+
private:
177+
/// Find the best index for splitting. The returned value is the index of the
178+
/// last hot basic block. Hence, "no splitting" is equivalent to returning the
179+
/// value which is one less than the size of the function.
180+
size_t findSplitIndex(const BinaryFunction &BF,
181+
const BasicBlockOrder &BlockOrder) {
182+
// Placeholder: hot-warm split after entry block.
183+
return 0;
184+
}
185+
};
186+
139187
struct SplitRandom2 final : public SplitStrategy {
140188
std::minstd_rand0 Gen;
141189

142190
SplitRandom2() : Gen(opts::RandomSeed.getValue()) {}
143191

144192
bool canSplit(const BinaryFunction &BF) override { return true; }
145193

146-
bool keepEmpty() override { return false; }
194+
bool compactFragments() override { return true; }
147195

148196
void fragment(const BlockIt Start, const BlockIt End) override {
149197
using DiffT = typename std::iterator_traits<BlockIt>::difference_type;
@@ -170,7 +218,7 @@ struct SplitRandomN final : public SplitStrategy {
170218

171219
bool canSplit(const BinaryFunction &BF) override { return true; }
172220

173-
bool keepEmpty() override { return false; }
221+
bool compactFragments() override { return true; }
174222

175223
void fragment(const BlockIt Start, const BlockIt End) override {
176224
using DiffT = typename std::iterator_traits<BlockIt>::difference_type;
@@ -217,10 +265,10 @@ struct SplitRandomN final : public SplitStrategy {
217265
struct SplitAll final : public SplitStrategy {
218266
bool canSplit(const BinaryFunction &BF) override { return true; }
219267

220-
bool keepEmpty() override {
268+
bool compactFragments() override {
221269
// Keeping empty fragments allows us to test, that empty fragments do not
222270
// generate symbols.
223-
return true;
271+
return false;
224272
}
225273

226274
void fragment(const BlockIt Start, const BlockIt End) override {
@@ -246,10 +294,26 @@ void SplitFunctions::runOnFunctions(BinaryContext &BC) {
246294
if (!opts::SplitFunctions)
247295
return;
248296

297+
// If split strategy is not CDSplit, then a second run of the pass is not
298+
// needed after function reordering.
299+
if (BC.HasFinalizedFunctionOrder &&
300+
opts::SplitStrategy != SplitFunctionsStrategy::CDSplit)
301+
return;
302+
249303
std::unique_ptr<SplitStrategy> Strategy;
250304
bool ForceSequential = false;
251305

252306
switch (opts::SplitStrategy) {
307+
case SplitFunctionsStrategy::CDSplit:
308+
// CDSplit runs two splitting passes: hot-cold splitting (SplitPrfoile2)
309+
// before function reordering and hot-warm-cold splitting
310+
// (SplitCacheDirected) after function reordering.
311+
if (BC.HasFinalizedFunctionOrder)
312+
Strategy = std::make_unique<SplitCacheDirected>();
313+
else
314+
Strategy = std::make_unique<SplitProfile2>();
315+
opts::AggressiveSplitting = true;
316+
break;
253317
case SplitFunctionsStrategy::Profile2:
254318
Strategy = std::make_unique<SplitProfile2>();
255319
break;
@@ -382,7 +446,7 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
382446
CurrentFragment = BB->getFragmentNum();
383447
}
384448

385-
if (!S.keepEmpty()) {
449+
if (S.compactFragments()) {
386450
FragmentNum CurrentFragment = FragmentNum::main();
387451
FragmentNum NewFragment = FragmentNum::main();
388452
for (BinaryBasicBlock *const BB : NewLayout) {
@@ -394,7 +458,7 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
394458
}
395459
}
396460

397-
BF.getLayout().update(NewLayout);
461+
const bool LayoutUpdated = BF.getLayout().update(NewLayout);
398462

399463
// For shared objects, invoke instructions and corresponding landing pads
400464
// have to be placed in the same fragment. When we split them, create
@@ -404,7 +468,7 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
404468
Trampolines = createEHTrampolines(BF);
405469

406470
// Check the new size to see if it's worth splitting the function.
407-
if (BC.isX86() && BF.isSplit()) {
471+
if (BC.isX86() && LayoutUpdated) {
408472
std::tie(HotSize, ColdSize) = BC.calculateEmittedSize(BF);
409473
LLVM_DEBUG(dbgs() << "Estimated size for function " << BF
410474
<< " post-split is <0x" << Twine::utohexstr(HotSize)
@@ -431,6 +495,11 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
431495
SplitBytesCold += ColdSize;
432496
}
433497
}
498+
499+
// Fix branches if the splitting decision of the pass after function
500+
// reordering is different from that of the pass before function reordering.
501+
if (LayoutUpdated && BC.HasFinalizedFunctionOrder)
502+
BF.fixBranches();
434503
}
435504

436505
SplitFunctions::TrampolineSetType

bolt/lib/Rewrite/BinaryPassManager.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,13 @@ void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
430430
Manager.registerPass(
431431
std::make_unique<ReorderFunctions>(PrintReorderedFunctions));
432432

433+
// This is the second run of the SplitFunctions pass required by certain
434+
// splitting strategies (e.g. cdsplit). Running the SplitFunctions pass again
435+
// after ReorderFunctions allows the finalized function order to be utilized
436+
// to make more sophisticated splitting decisions, like hot-warm-cold
437+
// splitting.
438+
Manager.registerPass(std::make_unique<SplitFunctions>(PrintSplit));
439+
433440
// Print final dyno stats right while CFG and instruction analysis are intact.
434441
Manager.registerPass(
435442
std::make_unique<DynoStatsPrintPass>(

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ C++2c Feature Support
182182
This is applied to both C++ standard attributes, and other attributes supported by Clang.
183183
This completes the implementation of `P2361R6 Unevaluated Strings <https://wg21.link/P2361R6>`_
184184

185+
- Implemented `P2864R2 Remove Deprecated Arithmetic Conversion on Enumerations From C++26 <https://wg21.link/P2864R2>`_.
186+
185187

186188
Resolutions to C++ Defect Reports
187189
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7220,6 +7220,11 @@ def warn_arith_conv_enum_float_cxx20 : Warning<
72207220
"%plural{2:with|4:from|:and}0 "
72217221
"%select{enumeration|floating-point}1 type %3 is deprecated">,
72227222
InGroup<DeprecatedEnumFloatConversion>;
7223+
def err_arith_conv_enum_float_cxx26 : Error<
7224+
"invalid %sub{select_arith_conv_kind}0 "
7225+
"%select{floating-point|enumeration}1 type %2 "
7226+
"%plural{2:with|4:from|:and}0 "
7227+
"%select{enumeration|floating-point}1 type %3">;
72237228
def warn_arith_conv_mixed_enum_types : Warning<
72247229
"%sub{select_arith_conv_kind}0 "
72257230
"different enumeration types%diff{ ($ and $)|}1,2">,
@@ -7228,6 +7233,10 @@ def warn_arith_conv_mixed_enum_types_cxx20 : Warning<
72287233
"%sub{select_arith_conv_kind}0 "
72297234
"different enumeration types%diff{ ($ and $)|}1,2 is deprecated">,
72307235
InGroup<DeprecatedEnumEnumConversion>;
7236+
def err_conv_mixed_enum_types_cxx26 : Error<
7237+
"invalid %sub{select_arith_conv_kind}0 "
7238+
"different enumeration types%diff{ ($ and $)|}1,2">;
7239+
72317240
def warn_arith_conv_mixed_anon_enum_types : Warning<
72327241
warn_arith_conv_mixed_enum_types.Summary>,
72337242
InGroup<AnonEnumEnumConversion>, DefaultIgnore;

clang/include/clang/Format/Format.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3034,7 +3034,9 @@ struct FormatStyle {
30343034
bool isJson() const { return Language == LK_Json; }
30353035
bool isJavaScript() const { return Language == LK_JavaScript; }
30363036
bool isVerilog() const { return Language == LK_Verilog; }
3037-
bool isProto() const { return Language == LK_Proto; }
3037+
bool isProto() const {
3038+
return Language == LK_Proto || Language == LK_TextProto;
3039+
}
30383040

30393041
/// Language, this format style is targeted at.
30403042
/// \version 3.5

clang/lib/Format/ContinuationIndenter.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,9 +1229,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
12291229
return CurrentState.Indent;
12301230
}
12311231
if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
1232-
(Current.is(tok::greater) &&
1233-
(Style.Language == FormatStyle::LK_Proto ||
1234-
Style.Language == FormatStyle::LK_TextProto))) &&
1232+
(Current.is(tok::greater) && Style.isProto())) &&
12351233
State.Stack.size() > 1) {
12361234
if (Current.closesBlockOrBlockTypeList(Style))
12371235
return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
@@ -1278,9 +1276,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
12781276
if (Current.is(tok::identifier) && Current.Next &&
12791277
(!Style.isVerilog() || Current.Next->is(tok::colon)) &&
12801278
(Current.Next->is(TT_DictLiteral) ||
1281-
((Style.Language == FormatStyle::LK_Proto ||
1282-
Style.Language == FormatStyle::LK_TextProto) &&
1283-
Current.Next->isOneOf(tok::less, tok::l_brace)))) {
1279+
(Style.isProto() && Current.Next->isOneOf(tok::less, tok::l_brace)))) {
12841280
return CurrentState.Indent;
12851281
}
12861282
if (NextNonComment->is(TT_ObjCStringLiteral) &&
@@ -1798,9 +1794,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
17981794
Current.MatchingParen->Previous &&
17991795
Current.MatchingParen->Previous->is(tok::comma);
18001796
AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
1801-
Style.Language == FormatStyle::LK_Proto ||
1802-
Style.Language == FormatStyle::LK_TextProto ||
1803-
!Style.BinPackArguments ||
1797+
Style.isProto() || !Style.BinPackArguments ||
18041798
(NextNonComment && NextNonComment->isOneOf(
18051799
TT_DesignatedInitializerPeriod,
18061800
TT_DesignatedInitializerLSquare));

clang/lib/Format/FormatToken.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ bool FormatToken::opensBlockOrBlockTypeList(const FormatStyle &Style) const {
100100
(is(tok::l_brace) &&
101101
(getBlockKind() == BK_Block || is(TT_DictLiteral) ||
102102
(!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
103-
(is(tok::less) && (Style.Language == FormatStyle::LK_Proto ||
104-
Style.Language == FormatStyle::LK_TextProto));
103+
(is(tok::less) && Style.isProto());
105104
}
106105

107106
TokenRole::~TokenRole() {}

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,11 +1313,8 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) {
13131313
}
13141314
}
13151315

1316-
if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Proto ||
1317-
Style.Language == FormatStyle::LK_TextProto) &&
1318-
Tok.is(tok::char_constant)) {
1316+
if ((Style.isJavaScript() || Style.isProto()) && Tok.is(tok::char_constant))
13191317
Tok.Tok.setKind(tok::string_literal);
1320-
}
13211318

13221319
if (Tok.is(tok::comment) && isClangFormatOn(Tok.TokenText))
13231320
FormattingDisabled = false;

0 commit comments

Comments
 (0)