Skip to content

Commit 2fa692a

Browse files
authored
Merge branch 'main' into add-type-base-for-fneg
2 parents db37270 + c3edeaa commit 2fa692a

Some content is hidden

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

44 files changed

+2482
-1212
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ Bug Fixes to C++ Support
589589
- Fixed an assertion failure in range calculations for conditional throw expressions. (#GH111854)
590590
- Clang now correctly ignores previous partial specializations of member templates explicitly specialized for
591591
an implicitly instantiated class template specialization. (#GH51051)
592+
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
592593

593594
Bug Fixes to AST Handling
594595
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,12 @@ defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling",
17861786
PosFlag<SetTrue, [], [ClangOption, CC1Option],
17871787
"Emit extra debug info to make sample profile more accurate">,
17881788
NegFlag<SetFalse>>;
1789+
def fprofile_generate_cold_function_coverage : Flag<["-"], "fprofile-generate-cold-function-coverage">,
1790+
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
1791+
HelpText<"Generate instrumented code to collect coverage info for cold functions into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">;
1792+
def fprofile_generate_cold_function_coverage_EQ : Joined<["-"], "fprofile-generate-cold-function-coverage=">,
1793+
Group<f_Group>, Visibility<[ClangOption, CLOption]>, MetaVarName<"<directory>">,
1794+
HelpText<"Generate instrumented code to collect coverage info for cold functions into <directory>/default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
17891795
def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
17901796
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
17911797
HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">;

clang/lib/Driver/ToolChain.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,9 @@ bool ToolChain::needsProfileRT(const ArgList &Args) {
899899
Args.hasArg(options::OPT_fprofile_instr_generate) ||
900900
Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
901901
Args.hasArg(options::OPT_fcreate_profile) ||
902-
Args.hasArg(options::OPT_forder_file_instrumentation);
902+
Args.hasArg(options::OPT_forder_file_instrumentation) ||
903+
Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage) ||
904+
Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage_EQ);
903905
}
904906

905907
bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,28 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
632632
}
633633
}
634634

635+
if (auto *ColdFuncCoverageArg = Args.getLastArg(
636+
options::OPT_fprofile_generate_cold_function_coverage,
637+
options::OPT_fprofile_generate_cold_function_coverage_EQ)) {
638+
SmallString<128> Path(
639+
ColdFuncCoverageArg->getOption().matches(
640+
options::OPT_fprofile_generate_cold_function_coverage_EQ)
641+
? ColdFuncCoverageArg->getValue()
642+
: "");
643+
llvm::sys::path::append(Path, "default_%m.profraw");
644+
// FIXME: Idealy the file path should be passed through
645+
// `-fprofile-instrument-path=`(InstrProfileOutput), however, this field is
646+
// shared with other profile use path(see PGOOptions), we need to refactor
647+
// PGOOptions to make it work.
648+
CmdArgs.push_back("-mllvm");
649+
CmdArgs.push_back(Args.MakeArgString(
650+
Twine("--instrument-cold-function-only-path=") + Path));
651+
CmdArgs.push_back("-mllvm");
652+
CmdArgs.push_back("--pgo-instrument-cold-function-only");
653+
CmdArgs.push_back("-mllvm");
654+
CmdArgs.push_back("--pgo-function-entry-coverage");
655+
}
656+
635657
Arg *PGOGenArg = nullptr;
636658
if (PGOGenerateArg) {
637659
assert(!CSPGOGenerateArg);

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17955,6 +17955,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
1795517955
<< Name;
1795617956
Invalid = true;
1795717957
}
17958+
if (TUK == TagUseKind::Declaration)
17959+
Invalid = true;
1795817960
} else if (!PrevDecl) {
1795917961
Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
1796017962
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Test -fprofile-generate-cold-function-coverage
2+
3+
// RUN: rm -rf %t && split-file %s %t
4+
// RUN: %clang --target=x86_64 -O2 -fprofile-generate-cold-function-coverage=/xxx/yyy/ -fprofile-sample-accurate -fprofile-sample-use=%t/pgo-cold-func.prof -S -emit-llvm -o - %t/pgo-cold-func.c | FileCheck %s
5+
6+
// CHECK: @__llvm_profile_filename = {{.*}} c"/xxx/yyy/default_%m.profraw\00"
7+
8+
// CHECK: store i8 0, ptr @__profc_bar, align 1
9+
// CHECK-NOT: @__profc_foo
10+
11+
//--- pgo-cold-func.prof
12+
foo:1:1
13+
1: 1
14+
15+
//--- pgo-cold-func.c
16+
int bar(int x) { return x;}
17+
int foo(int x) {
18+
return x;
19+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang -### -c -fprofile-generate-cold-function-coverage %s 2>&1 | FileCheck %s
2+
// CHECK: "--instrument-cold-function-only-path=default_%m.profraw"
3+
// CHECK: "--pgo-instrument-cold-function-only"
4+
// CHECK: "--pgo-function-entry-coverage"
5+
// CHECK-NOT: "-fprofile-instrument"
6+
// CHECK-NOT: "-fprofile-instrument-path=
7+
8+
// RUN: %clang -### -c -fprofile-generate-cold-function-coverage=dir %s 2>&1 | FileCheck %s --check-prefix=CHECK-EQ
9+
// CHECK-EQ: "--instrument-cold-function-only-path=dir{{/|\\\\}}default_%m.profraw"

clang/test/SemaCXX/enum.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,11 @@ struct PR28903 {
143143
})
144144
};
145145
};
146+
147+
namespace GH112208 {
148+
class C {
149+
enum E { e = 0 };
150+
void f(int, enum E;); // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
151+
// expected-error {{unexpected ';' before ')'}}
152+
};
153+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//===- StableFunctionMap.h -------------------------------------*- 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+
// This defines the StableFunctionMap class, to track similar functions.
10+
// It provides a mechanism to map stable hashes of functions to their
11+
// corresponding metadata. It includes structures for storing function details
12+
// and methods for managing and querying these mappings.
13+
//
14+
//===---------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_CGDATA_STABLEFUNCTIONMAP_H
17+
#define LLVM_CGDATA_STABLEFUNCTIONMAP_H
18+
19+
#include "llvm/ADT/DenseMap.h"
20+
#include "llvm/ADT/StringMap.h"
21+
#include "llvm/IR/StructuralHash.h"
22+
23+
namespace llvm {
24+
25+
using IndexPairHash = std::pair<IndexPair, stable_hash>;
26+
using IndexOperandHashVecType = SmallVector<IndexPairHash>;
27+
28+
/// A stable function is a function with a stable hash while tracking the
29+
/// locations of ignored operands and their hashes.
30+
struct StableFunction {
31+
/// The combined stable hash of the function.
32+
stable_hash Hash;
33+
/// The name of the function.
34+
std::string FunctionName;
35+
/// The name of the module the function is in.
36+
std::string ModuleName;
37+
/// The number of instructions.
38+
unsigned InstCount;
39+
/// A vector of pairs of IndexPair and operand hash which was skipped.
40+
IndexOperandHashVecType IndexOperandHashes;
41+
42+
StableFunction(stable_hash Hash, const std::string FunctionName,
43+
const std::string ModuleName, unsigned InstCount,
44+
IndexOperandHashVecType &&IndexOperandHashes)
45+
: Hash(Hash), FunctionName(FunctionName), ModuleName(ModuleName),
46+
InstCount(InstCount),
47+
IndexOperandHashes(std::move(IndexOperandHashes)) {}
48+
StableFunction() = default;
49+
};
50+
51+
struct StableFunctionMap {
52+
/// An efficient form of StableFunction for fast look-up
53+
struct StableFunctionEntry {
54+
/// The combined stable hash of the function.
55+
stable_hash Hash;
56+
/// Id of the function name.
57+
unsigned FunctionNameId;
58+
/// Id of the module name.
59+
unsigned ModuleNameId;
60+
/// The number of instructions.
61+
unsigned InstCount;
62+
/// A map from an IndexPair to a stable_hash which was skipped.
63+
std::unique_ptr<IndexOperandHashMapType> IndexOperandHashMap;
64+
65+
StableFunctionEntry(
66+
stable_hash Hash, unsigned FunctionNameId, unsigned ModuleNameId,
67+
unsigned InstCount,
68+
std::unique_ptr<IndexOperandHashMapType> IndexOperandHashMap)
69+
: Hash(Hash), FunctionNameId(FunctionNameId),
70+
ModuleNameId(ModuleNameId), InstCount(InstCount),
71+
IndexOperandHashMap(std::move(IndexOperandHashMap)) {}
72+
};
73+
74+
using HashFuncsMapType =
75+
DenseMap<stable_hash, SmallVector<std::unique_ptr<StableFunctionEntry>>>;
76+
77+
/// Get the HashToFuncs map for serialization.
78+
const HashFuncsMapType &getFunctionMap() const { return HashToFuncs; }
79+
80+
/// Get the NameToId vector for serialization.
81+
const SmallVector<std::string> getNames() const { return IdToName; }
82+
83+
/// Get an existing ID associated with the given name or create a new ID if it
84+
/// doesn't exist.
85+
unsigned getIdOrCreateForName(StringRef Name);
86+
87+
/// Get the name associated with a given ID
88+
std::optional<std::string> getNameForId(unsigned Id) const;
89+
90+
/// Insert a `StableFunction` object into the function map. This method
91+
/// handles the uniquing of string names and create a `StableFunctionEntry`
92+
/// for insertion.
93+
void insert(const StableFunction &Func);
94+
95+
/// Merge a \p OtherMap into this function map.
96+
void merge(const StableFunctionMap &OtherMap);
97+
98+
/// \returns true if there is no stable function entry.
99+
bool empty() const { return size() == 0; }
100+
101+
enum SizeType {
102+
UniqueHashCount, // The number of unique hashes in HashToFuncs.
103+
TotalFunctionCount, // The number of total functions in HashToFuncs.
104+
MergeableFunctionCount, // The number of functions that can be merged based
105+
// on their hash.
106+
};
107+
108+
/// \returns the size of StableFunctionMap.
109+
/// \p Type is the type of size to return.
110+
size_t size(SizeType Type = UniqueHashCount) const;
111+
112+
/// Finalize the stable function map by trimming content.
113+
void finalize();
114+
115+
private:
116+
/// Insert a `StableFunctionEntry` into the function map directly. This
117+
/// method assumes that string names have already been uniqued and the
118+
/// `StableFunctionEntry` is ready for insertion.
119+
void insert(std::unique_ptr<StableFunctionEntry> FuncEntry) {
120+
assert(!Finalized && "Cannot insert after finalization");
121+
HashToFuncs[FuncEntry->Hash].emplace_back(std::move(FuncEntry));
122+
}
123+
124+
/// A map from a stable_hash to a vector of functions with that hash.
125+
HashFuncsMapType HashToFuncs;
126+
/// A vector of strings to hold names.
127+
SmallVector<std::string> IdToName;
128+
/// A map from StringRef (name) to an ID.
129+
StringMap<unsigned> NameToId;
130+
/// True if the function map is finalized with minimal content.
131+
bool Finalized = false;
132+
133+
friend struct StableFunctionMapRecord;
134+
};
135+
136+
} // namespace llvm
137+
138+
#endif
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===- StableFunctionMapRecord.h -------------------------------*- 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+
// This defines the StableFunctionMapRecord structure, which provides
10+
// functionality for managing and serializing a StableFunctionMap. It includes
11+
// methods for serialization to and from raw and YAML streams, as well as
12+
// utilities for merging and finalizing function maps.
13+
//
14+
//===---------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_CGDATA_STABLEFUNCTIONMAPRECORD_H
17+
#define LLVM_CGDATA_STABLEFUNCTIONMAPRECORD_H
18+
19+
#include "llvm/CGData/StableFunctionMap.h"
20+
#include "llvm/ObjectYAML/YAML.h"
21+
#include "llvm/Support/raw_ostream.h"
22+
23+
namespace llvm {
24+
25+
struct StableFunctionMapRecord {
26+
std::unique_ptr<StableFunctionMap> FunctionMap;
27+
28+
StableFunctionMapRecord() {
29+
FunctionMap = std::make_unique<StableFunctionMap>();
30+
}
31+
32+
StableFunctionMapRecord(std::unique_ptr<StableFunctionMap> FunctionMap)
33+
: FunctionMap(std::move(FunctionMap)) {}
34+
35+
/// A static helper function to serialize the stable function map without
36+
/// owning the stable function map.
37+
static void serialize(raw_ostream &OS, const StableFunctionMap *FunctionMap);
38+
39+
/// Serialize the stable function map to a raw_ostream.
40+
void serialize(raw_ostream &OS) const;
41+
42+
/// Deserialize the stable function map from a raw_ostream.
43+
void deserialize(const unsigned char *&Ptr);
44+
45+
/// Serialize the stable function map to a YAML stream.
46+
void serializeYAML(yaml::Output &YOS) const;
47+
48+
/// Deserialize the stable function map from a YAML stream.
49+
void deserializeYAML(yaml::Input &YIS);
50+
51+
/// Finalize the stable function map by trimming content.
52+
void finalize() { FunctionMap->finalize(); }
53+
54+
/// Merge the stable function map into this one.
55+
void merge(const StableFunctionMapRecord &Other) {
56+
FunctionMap->merge(*Other.FunctionMap);
57+
}
58+
59+
/// \returns true if the stable function map is empty.
60+
bool empty() const { return FunctionMap->empty(); }
61+
62+
/// Print the stable function map in a YAML format.
63+
void print(raw_ostream &OS = llvm::errs()) const {
64+
yaml::Output YOS(OS);
65+
serializeYAML(YOS);
66+
}
67+
};
68+
69+
} // namespace llvm
70+
71+
#endif

llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,11 @@ inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) {
273273
LegalityPredicate
274274
typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1,
275275
std::initializer_list<std::pair<LLT, LLT>> TypesInit);
276+
/// True iff the given types for the given tuple of type indexes is one of the
277+
/// specified type tuple.
278+
LegalityPredicate
279+
typeTupleInSet(unsigned TypeIdx0, unsigned TypeIdx1, unsigned Type2,
280+
std::initializer_list<std::tuple<LLT, LLT, LLT>> TypesInit);
276281
/// True iff the given types for the given pair of type indexes is one of the
277282
/// specified type pairs.
278283
LegalityPredicate typePairAndMemDescInSet(
@@ -504,6 +509,15 @@ class LegalizeRuleSet {
504509
using namespace LegalityPredicates;
505510
return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
506511
}
512+
513+
LegalizeRuleSet &
514+
actionFor(LegalizeAction Action,
515+
std::initializer_list<std::tuple<LLT, LLT, LLT>> Types) {
516+
using namespace LegalityPredicates;
517+
return actionIf(Action,
518+
typeTupleInSet(typeIdx(0), typeIdx(1), typeIdx(2), Types));
519+
}
520+
507521
/// Use the given action when type indexes 0 and 1 is any type pair in the
508522
/// given list.
509523
/// Action should be an action that requires mutation.
@@ -615,6 +629,12 @@ class LegalizeRuleSet {
615629
return *this;
616630
return actionFor(LegalizeAction::Legal, Types);
617631
}
632+
LegalizeRuleSet &
633+
legalFor(bool Pred, std::initializer_list<std::tuple<LLT, LLT, LLT>> Types) {
634+
if (!Pred)
635+
return *this;
636+
return actionFor(LegalizeAction::Legal, Types);
637+
}
618638
/// The instruction is legal when type index 0 is any type in the given list
619639
/// and imm index 0 is anything.
620640
LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) {

llvm/lib/CGData/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ add_llvm_component_library(LLVMCGData
44
CodeGenDataWriter.cpp
55
OutlinedHashTree.cpp
66
OutlinedHashTreeRecord.cpp
7+
StableFunctionMap.cpp
8+
StableFunctionMapRecord.cpp
79

810
ADDITIONAL_HEADER_DIRS
911
${LLVM_MAIN_INCLUDE_DIR}/llvm/CGData

0 commit comments

Comments
 (0)