Skip to content

Commit 9bfc3ae

Browse files
committed
LLVM and SPIRV-LLVM-Translator pulldown (WW52)
LLVM: llvm/llvm-project@bc8c4bb SPIRV-LLVM-Translator: KhronosGroup/SPIRV-LLVM-Translator@e63fdb8
2 parents 367166c + c99ffd5 commit 9bfc3ae

File tree

884 files changed

+53233
-22453
lines changed

Some content is hidden

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

884 files changed

+53233
-22453
lines changed

.github/workflows/libcxx-build-and-test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ jobs:
185185
std_modules: 'OFF'
186186
# Use a larger machine for MSAN to avoid timeout and memory allocation issues.
187187
- config: 'generic-msan'
188-
machine: libcxx-runners-32-set
188+
machine: libcxx-runners-8-set
189189
std_modules: 'OFF'
190190
runs-on: ${{ matrix.machine }}
191191
steps:

bolt/lib/Core/DIEBuilder.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,11 @@ void DIEBuilder::buildCompileUnits(const bool Init) {
266266
}
267267
void DIEBuilder::buildCompileUnits(const std::vector<DWARFUnit *> &CUs) {
268268
BuilderState.reset(new State());
269-
// Initializing to full size because there could be cross CU references with
270-
// different abbrev offsets. LLVM happens to output CUs that have cross CU
271-
// references with the same abbrev table. So destinations end up in the first
272-
// set, even if they themselves don't have src cross cu ref. We could have
273-
// cases where this is not the case. In which case this container needs to be
274-
// big enough for all.
275-
getState().CloneUnitCtxMap.resize(DwarfContext->getNumCompileUnits());
269+
// Allocating enough for current batch being processed.
270+
// In real use cases we either processing a batch of CUs with no cross
271+
// references, or if they do have them it is due to LTO. With clang they will
272+
// share the same abbrev table. In either case this vector will not grow.
273+
getState().CloneUnitCtxMap.resize(CUs.size());
276274
getState().Type = ProcessingType::CUs;
277275
for (DWARFUnit *CU : CUs)
278276
registerUnit(*CU, false);
@@ -897,6 +895,10 @@ void DIEBuilder::registerUnit(DWARFUnit &DU, bool NeedSort) {
897895
});
898896
}
899897
getState().UnitIDMap[getHash(DU)] = getState().DUList.size();
898+
// This handles the case where we do have cross cu references, but CUs do not
899+
// share the same abbrev table.
900+
if (getState().DUList.size() == getState().CloneUnitCtxMap.size())
901+
getState().CloneUnitCtxMap.emplace_back();
900902
getState().DUList.push_back(&DU);
901903
}
902904

bolt/lib/Passes/SplitFunctions.cpp

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,12 @@ struct SplitCacheDirected final : public SplitStrategy {
175175
void fragment(const BlockIt Start, const BlockIt End) override {
176176
BasicBlockOrder BlockOrder(Start, End);
177177
BinaryFunction &BF = *BlockOrder.front()->getFunction();
178+
// No need to re-split small functions.
179+
if (BlockOrder.size() <= 2)
180+
return;
178181

179182
size_t BestSplitIndex = findSplitIndex(BF, BlockOrder);
183+
assert(BestSplitIndex < BlockOrder.size());
180184

181185
// Assign fragments based on the computed best split index.
182186
// All basic blocks with index up to the best split index become hot.
@@ -200,10 +204,12 @@ struct SplitCacheDirected final : public SplitStrategy {
200204
};
201205

202206
struct SplitScore {
203-
size_t SplitIndex;
207+
size_t SplitIndex = size_t(-1);
204208
size_t HotSizeReduction = 0;
205209
double LocalScore = 0;
206210
double CoverCallScore = 0;
211+
212+
double sum() const { return LocalScore + CoverCallScore; }
207213
};
208214

209215
// Auxiliary variables used by the algorithm.
@@ -303,7 +309,7 @@ struct SplitCacheDirected final : public SplitStrategy {
303309
const size_t SplitIndex) {
304310
assert(SplitIndex < BlockOrder.size() && "Invalid split index");
305311

306-
// Update function layout assuming hot-warm splitting at SplitIndex
312+
// Update function layout assuming hot-warm splitting at SplitIndex.
307313
for (size_t Index = 0; Index < BlockOrder.size(); Index++) {
308314
BinaryBasicBlock *BB = BlockOrder[Index];
309315
if (BB->getFragmentNum() == FragmentNum::cold())
@@ -319,8 +325,8 @@ struct SplitCacheDirected final : public SplitStrategy {
319325
// Populate BB.OutputAddressRange with estimated new start and end addresses
320326
// and compute the old end address of the hot section and the new end
321327
// address of the hot section.
322-
size_t OldHotEndAddr;
323-
size_t NewHotEndAddr;
328+
size_t OldHotEndAddr{0};
329+
size_t NewHotEndAddr{0};
324330
size_t CurrentAddr = BBOffsets[BlockOrder[0]];
325331
for (BinaryBasicBlock *BB : BlockOrder) {
326332
// We only care about new addresses of blocks in hot/warm.
@@ -492,20 +498,15 @@ struct SplitCacheDirected final : public SplitStrategy {
492498
}
493499

494500
/// Compute the split score of splitting a function at a given index.
495-
/// The split score consists of local score and cover score. Cover call score
496-
/// is expensive to compute. As a result, we pass in a \p ReferenceScore and
497-
/// compute cover score only when the local score exceeds that in the
498-
/// ReferenceScore or that the size reduction of the hot fragment is larger
499-
/// than that achieved by the split index of the ReferenceScore. This function
500-
/// returns \p Score of SplitScore type. It contains the local score and cover
501-
/// score (if computed) of the current splitting index. For easier book
502-
/// keeping and comparison, it also stores the split index and the resulting
503-
/// reduction in hot fragment size.
501+
/// The split score consists of local score and cover score. This function
502+
/// returns \p Score of SplitScore type. It contains the local score and
503+
/// cover score of the current splitting index. For easier book keeping and
504+
/// comparison, it also stores the split index and the resulting reduction
505+
/// in hot fragment size.
504506
SplitScore computeSplitScore(const BinaryFunction &BF,
505507
const BasicBlockOrder &BlockOrder,
506508
const size_t SplitIndex,
507-
const std::vector<CallInfo> &CoverCalls,
508-
const SplitScore &ReferenceScore) {
509+
const std::vector<CallInfo> &CoverCalls) {
509510
// Populate BinaryBasicBlock::OutputAddressRange with estimated
510511
// new start and end addresses after hot-warm splitting at SplitIndex.
511512
size_t OldHotEnd;
@@ -533,47 +534,74 @@ struct SplitCacheDirected final : public SplitStrategy {
533534
// increamented in place.
534535
computeJumpScore(BlockOrder, SplitIndex, Score);
535536

536-
// There is no need to compute CoverCallScore if we have already found
537-
// another split index with a bigger LocalScore and bigger HotSizeReduction.
538-
if (Score.LocalScore <= ReferenceScore.LocalScore &&
539-
Score.HotSizeReduction <= ReferenceScore.HotSizeReduction)
540-
return Score;
541-
542537
// Compute CoverCallScore and store in Score in place.
543538
computeCoverCallScore(BlockOrder, SplitIndex, CoverCalls, Score);
544539
return Score;
545540
}
546541

542+
/// Find the most likely successor of a basic block when it has one or two
543+
/// successors. Return nullptr otherwise.
544+
const BinaryBasicBlock *getMostLikelySuccessor(const BinaryBasicBlock *BB) {
545+
if (BB->succ_size() == 1)
546+
return BB->getSuccessor();
547+
if (BB->succ_size() == 2) {
548+
uint64_t TakenCount = BB->getTakenBranchInfo().Count;
549+
assert(TakenCount != BinaryBasicBlock::COUNT_NO_PROFILE);
550+
uint64_t NonTakenCount = BB->getFallthroughBranchInfo().Count;
551+
assert(NonTakenCount != BinaryBasicBlock::COUNT_NO_PROFILE);
552+
if (TakenCount > NonTakenCount)
553+
return BB->getConditionalSuccessor(true);
554+
else if (TakenCount < NonTakenCount)
555+
return BB->getConditionalSuccessor(false);
556+
}
557+
return nullptr;
558+
}
559+
547560
/// Find the best index for splitting. The returned value is the index of the
548561
/// last hot basic block. Hence, "no splitting" is equivalent to returning the
549562
/// value which is one less than the size of the function.
550563
size_t findSplitIndex(const BinaryFunction &BF,
551564
const BasicBlockOrder &BlockOrder) {
565+
assert(BlockOrder.size() > 2);
552566
// Find all function calls that can be shortened if we move blocks of the
553567
// current function to warm/cold
554568
const std::vector<CallInfo> CoverCalls = extractCoverCalls(BF);
555569

556-
// Try all possible split indices (blocks with Index <= SplitIndex are in
557-
// hot) and find the one maximizing the splitting score.
570+
// Find the existing hot-cold splitting index.
571+
size_t HotColdIndex = 0;
572+
while (HotColdIndex + 1 < BlockOrder.size()) {
573+
if (BlockOrder[HotColdIndex + 1]->getFragmentNum() == FragmentNum::cold())
574+
break;
575+
HotColdIndex++;
576+
}
577+
assert(HotColdIndex + 1 == BlockOrder.size() ||
578+
(BlockOrder[HotColdIndex]->getFragmentNum() == FragmentNum::main() &&
579+
BlockOrder[HotColdIndex + 1]->getFragmentNum() ==
580+
FragmentNum::cold()));
581+
582+
// Try all possible split indices up to HotColdIndex (blocks that have
583+
// Index <= SplitIndex are in hot) and find the one maximizing the
584+
// splitting score.
558585
SplitScore BestScore;
559-
double BestScoreSum = -1.0;
560-
SplitScore ReferenceScore;
561-
for (size_t Index = 0; Index < BlockOrder.size(); Index++) {
586+
for (size_t Index = 0; Index <= HotColdIndex; Index++) {
562587
const BinaryBasicBlock *LastHotBB = BlockOrder[Index];
563-
// No need to keep cold blocks in the hot section.
564-
if (LastHotBB->getFragmentNum() == FragmentNum::cold())
565-
break;
588+
assert(LastHotBB->getFragmentNum() != FragmentNum::cold());
589+
590+
// Do not break jump to the most likely successor.
591+
if (Index + 1 < BlockOrder.size() &&
592+
BlockOrder[Index + 1] == getMostLikelySuccessor(LastHotBB))
593+
continue;
594+
566595
const SplitScore Score =
567-
computeSplitScore(BF, BlockOrder, Index, CoverCalls, ReferenceScore);
568-
double ScoreSum = Score.LocalScore + Score.CoverCallScore;
569-
if (ScoreSum > BestScoreSum) {
570-
BestScoreSum = ScoreSum;
596+
computeSplitScore(BF, BlockOrder, Index, CoverCalls);
597+
if (Score.sum() > BestScore.sum())
571598
BestScore = Score;
572-
}
573-
if (Score.LocalScore > ReferenceScore.LocalScore)
574-
ReferenceScore = Score;
575599
}
576600

601+
// If we don't find a good splitting point, fallback to the original one.
602+
if (BestScore.SplitIndex == size_t(-1))
603+
return HotColdIndex;
604+
577605
return BestScore.SplitIndex;
578606
}
579607
};

bolt/test/X86/cdsplit-call-scale.s

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# When -call-scale=0.0, the tested function is 2-way splitted.
33
# When -call-scale=1.0, the tested function is 3-way splitted with 5 blocks
44
# in warm because of the increased benefit of shortening the call edges.
5-
# When -call-scale=1000.0, the tested function is 3-way splitted with 7 blocks
6-
# in warm because of the strong benefit of shortening the call edges.
5+
# When -call-scale=1000.0, the tested function is still 3-way splitted with
6+
# 5 blocks in warm because cdsplit does not allow hot-warm splitting to break
7+
# a fall through branch from a basic block to its most likely successor.
78

89
# RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %s -o %t.o
910
# RUN: link_fdata %s %t.o %t.fdata
@@ -39,12 +40,10 @@
3940
# MEDINCENTIVE: {{^\.Ltmp5}}
4041

4142
# HIGHINCENTIVE: Binary Function "chain" after split-functions
42-
# HIGHINCENTIVE: {{^\.LBB00}}
43+
# HIGHINCENTIVE: {{^\.Ltmp1}}
4344
# HIGHINCENTIVE: ------- HOT-COLD SPLIT POINT -------
4445
# HIGHINCENTIVE: {{^\.LFT1}}
4546
# HIGHINCENTIVE: ------- HOT-COLD SPLIT POINT -------
46-
# HIGHINCENTIVE: {{^\.LFT0}}
47-
# HIGHINCENTIVE: {{^\.Ltmp1}}
4847
# HIGHINCENTIVE: {{^\.Ltmp0}}
4948
# HIGHINCENTIVE: {{^\.Ltmp2}}
5049
# HIGHINCENTIVE: {{^\.Ltmp3}}

clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
#include "UnhandledSelfAssignmentCheck.h"
8484
#include "UniquePtrArrayMismatchCheck.h"
8585
#include "UnsafeFunctionsCheck.h"
86+
#include "UnusedLocalNonTrivialVariableCheck.h"
8687
#include "UnusedRaiiCheck.h"
8788
#include "UnusedReturnValueCheck.h"
8889
#include "UseAfterMoveCheck.h"
@@ -235,6 +236,8 @@ class BugproneModule : public ClangTidyModule {
235236
"bugprone-unique-ptr-array-mismatch");
236237
CheckFactories.registerCheck<UnsafeFunctionsCheck>(
237238
"bugprone-unsafe-functions");
239+
CheckFactories.registerCheck<UnusedLocalNonTrivialVariableCheck>(
240+
"bugprone-unused-local-non-trivial-variable");
238241
CheckFactories.registerCheck<UnusedRaiiCheck>("bugprone-unused-raii");
239242
CheckFactories.registerCheck<UnusedReturnValueCheck>(
240243
"bugprone-unused-return-value");

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ add_clang_library(clangTidyBugproneModule
7979
UnhandledSelfAssignmentCheck.cpp
8080
UniquePtrArrayMismatchCheck.cpp
8181
UnsafeFunctionsCheck.cpp
82+
UnusedLocalNonTrivialVariableCheck.cpp
8283
UnusedRaiiCheck.cpp
8384
UnusedReturnValueCheck.cpp
8485
UseAfterMoveCheck.cpp
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===--- UnusedLocalNonTrivialVariableCheck.cpp - clang-tidy --------------===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "UnusedLocalNonTrivialVariableCheck.h"
10+
#include "../utils/Matchers.h"
11+
#include "../utils/OptionsUtils.h"
12+
#include "clang/AST/ASTContext.h"
13+
#include "clang/AST/ASTTypeTraits.h"
14+
#include "clang/AST/Type.h"
15+
#include "clang/ASTMatchers/ASTMatchFinder.h"
16+
#include "clang/ASTMatchers/ASTMatchers.h"
17+
#include "clang/ASTMatchers/ASTMatchersMacros.h"
18+
19+
using namespace clang::ast_matchers;
20+
using namespace clang::tidy::matchers;
21+
22+
namespace clang::tidy::bugprone {
23+
24+
namespace {
25+
static constexpr StringRef DefaultIncludeTypeRegex =
26+
"::std::.*mutex;::std::future;::std::basic_string;::std::basic_regex;"
27+
"::std::basic_istringstream;::std::basic_stringstream;::std::bitset;"
28+
"::std::filesystem::path";
29+
30+
AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); }
31+
AST_MATCHER(VarDecl, isReferenced) { return Node.isReferenced(); }
32+
AST_MATCHER(Type, isReferenceType) { return Node.isReferenceType(); }
33+
AST_MATCHER(QualType, isTrivial) {
34+
return Node.isTrivialType(Finder->getASTContext()) ||
35+
Node.isTriviallyCopyableType(Finder->getASTContext());
36+
}
37+
} // namespace
38+
39+
UnusedLocalNonTrivialVariableCheck::UnusedLocalNonTrivialVariableCheck(
40+
StringRef Name, ClangTidyContext *Context)
41+
: ClangTidyCheck(Name, Context),
42+
IncludeTypes(utils::options::parseStringList(
43+
Options.get("IncludeTypes", DefaultIncludeTypeRegex))),
44+
ExcludeTypes(
45+
utils::options::parseStringList(Options.get("ExcludeTypes", ""))) {}
46+
47+
void UnusedLocalNonTrivialVariableCheck::storeOptions(
48+
ClangTidyOptions::OptionMap &Opts) {
49+
Options.store(Opts, "IncludeTypes",
50+
utils::options::serializeStringList(IncludeTypes));
51+
Options.store(Opts, "ExcludeTypes",
52+
utils::options::serializeStringList(ExcludeTypes));
53+
}
54+
55+
void UnusedLocalNonTrivialVariableCheck::registerMatchers(MatchFinder *Finder) {
56+
if (IncludeTypes.empty())
57+
return;
58+
59+
Finder->addMatcher(
60+
varDecl(isLocalVarDecl(), unless(isReferenced()),
61+
unless(isExceptionVariable()), hasLocalStorage(), isDefinition(),
62+
unless(hasType(isReferenceType())), unless(hasType(isTrivial())),
63+
hasType(hasUnqualifiedDesugaredType(
64+
anyOf(recordType(hasDeclaration(namedDecl(
65+
matchesAnyListedName(IncludeTypes),
66+
unless(matchesAnyListedName(ExcludeTypes))))),
67+
templateSpecializationType(hasDeclaration(namedDecl(
68+
matchesAnyListedName(IncludeTypes),
69+
unless(matchesAnyListedName(ExcludeTypes)))))))))
70+
.bind("var"),
71+
this);
72+
}
73+
74+
void UnusedLocalNonTrivialVariableCheck::check(
75+
const MatchFinder::MatchResult &Result) {
76+
const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("var");
77+
diag(MatchedDecl->getLocation(), "unused local variable %0 of type %1")
78+
<< MatchedDecl << MatchedDecl->getType();
79+
}
80+
81+
bool UnusedLocalNonTrivialVariableCheck::isLanguageVersionSupported(
82+
const LangOptions &LangOpts) const {
83+
return LangOpts.CPlusPlus;
84+
}
85+
86+
std::optional<TraversalKind>
87+
UnusedLocalNonTrivialVariableCheck::getCheckTraversalKind() const {
88+
return TK_IgnoreUnlessSpelledInSource;
89+
}
90+
91+
} // namespace clang::tidy::bugprone
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===--- UnusedLocalNonTrivialVariableCheck.h - clang-tidy ------*- C++ -*-===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDLOCALNONTRIVIALVARIABLECHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDLOCALNONTRIVIALVARIABLECHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Warns when a local non trivial variable is unused within a function. By
17+
/// default std::.*mutex and std::future are included.
18+
///
19+
/// The check supports these options:
20+
/// - 'IncludeTypes': a semicolon-separated list of regular expressions
21+
/// matching types to ensure must be used.
22+
/// - 'ExcludeTypes': a semicolon-separated list of regular expressions
23+
/// matching types that are excluded from the
24+
/// 'IncludeTypes' matches.
25+
///
26+
/// For the user-facing documentation see:
27+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.html
28+
class UnusedLocalNonTrivialVariableCheck : public ClangTidyCheck {
29+
public:
30+
UnusedLocalNonTrivialVariableCheck(StringRef Name, ClangTidyContext *Context);
31+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
32+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
33+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
34+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
35+
std::optional<TraversalKind> getCheckTraversalKind() const override;
36+
37+
private:
38+
const std::vector<StringRef> IncludeTypes;
39+
const std::vector<StringRef> ExcludeTypes;
40+
};
41+
42+
} // namespace clang::tidy::bugprone
43+
44+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDLOCALNONTRIVIALVARIABLECHECK_H

0 commit comments

Comments
 (0)