Skip to content

Commit bb9eb19

Browse files
committed
Support for instrumenting only selected files or functions
This change implements support for applying profile instrumentation only to selected files or functions. The implementation uses the sanitizer special case list format to select which files and functions to instrument, and relies on the new noprofile IR attribute to exclude functions from instrumentation. Differential Revision: https://reviews.llvm.org/D94820
1 parent fc31920 commit bb9eb19

File tree

28 files changed

+404
-1
lines changed

28 files changed

+404
-1
lines changed

clang/docs/ClangCommandLineReference.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,12 @@ Set update method of profile counters (atomic,prefer-atomic,single)
20452045

20462046
Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.
20472047

2048+
.. program:: clang1
2049+
.. option:: -fprofile-list=<file>
2050+
.. program:: clang
2051+
2052+
Filename defining the list of functions/files to instrument. The file uses the sanitizer special case list format.
2053+
20482054
.. option:: -freciprocal-math, -fno-reciprocal-math
20492055

20502056
Allow division operations to be reassociated

clang/docs/UsersManual.rst

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,6 +2282,63 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or
22822282
Note that these flags should appear after the corresponding profile
22832283
flags to have an effect.
22842284

2285+
Instrumenting only selected files or functions
2286+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2287+
2288+
Sometimes it's useful to only instrument certain files or functions. For
2289+
example in automated testing infrastructure, it may be desirable to only
2290+
instrument files or functions that were modified by a patch to reduce the
2291+
overhead of instrumenting a full system.
2292+
2293+
This can be done using the ``-fprofile-list`` option.
2294+
2295+
.. option:: -fprofile-list=<pathname>
2296+
2297+
This option can be used to apply profile instrumentation only to selected
2298+
files or functions. ``pathname`` should point to a file in the
2299+
:doc:`SanitizerSpecialCaseList` format which selects which files and
2300+
functions to instrument.
2301+
2302+
.. code-block:: console
2303+
2304+
$ echo "fun:test" > fun.list
2305+
$ clang++ -O2 -fprofile-instr-generate -fprofile-list=fun.list code.cc -o code
2306+
2307+
The option can be specified multiple times to pass multiple files.
2308+
2309+
.. code-block:: console
2310+
2311+
$ echo "!fun:*test*" > fun.list
2312+
$ echo "src:code.cc" > src.list
2313+
% clang++ -O2 -fprofile-instr-generate -fcoverage-mapping -fprofile-list=fun.list -fprofile-list=code.list code.cc -o code
2314+
2315+
To filter individual functions or entire source files using ``fun:<name>`` or
2316+
``src:<file>`` respectively. To exclude a function or a source file, use
2317+
``!fun:<name>`` or ``!src:<file>`` respectively. The format also supports
2318+
wildcard expansion. The compiler generated functions are assumed to be located
2319+
in the main source file. It is also possible to restrict the filter to a
2320+
particular instrumentation type by using a named section.
2321+
2322+
.. code-block:: none
2323+
2324+
# all functions whose name starts with foo will be instrumented.
2325+
fun:foo*
2326+
2327+
# except for foo1 which will be excluded from instrumentation.
2328+
!fun:foo1
2329+
2330+
# every function in path/to/foo.cc will be instrumented.
2331+
src:path/to/foo.cc
2332+
2333+
# bar will be instrumented only when using backend instrumentation.
2334+
# Recognized section names are clang, llvm and csllvm.
2335+
[llvm]
2336+
fun:bar
2337+
2338+
When the file contains only excludes, all files and functions except for the
2339+
excluded ones will be instrumented. Otherwise, only the files and functions
2340+
specified will be instrumented.
2341+
22852342
Profile remapping
22862343
^^^^^^^^^^^^^^^^^
22872344

@@ -3740,6 +3797,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
37403797
Use instrumentation data for profile-guided optimization
37413798
-fprofile-remapping-file=<file>
37423799
Use the remappings described in <file> to match the profile data against names in the program
3800+
-fprofile-list=<file>
3801+
Filename defining the list of functions/files to instrument
37433802
-fsanitize-address-field-padding=<value>
37443803
Level of field padding for AddressSanitizer
37453804
-fsanitize-address-globals-dead-stripping

clang/include/clang/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "clang/Basic/Linkage.h"
3737
#include "clang/Basic/OperatorKinds.h"
3838
#include "clang/Basic/PartialDiagnostic.h"
39+
#include "clang/Basic/ProfileList.h"
3940
#include "clang/Basic/SanitizerBlacklist.h"
4041
#include "clang/Basic/SourceLocation.h"
4142
#include "clang/Basic/Specifiers.h"
@@ -566,6 +567,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
566567
/// should be imbued with the XRay "always" or "never" attributes.
567568
std::unique_ptr<XRayFunctionFilter> XRayFilter;
568569

570+
/// ProfileList object that is used by the profile instrumentation
571+
/// to decide which entities should be instrumented.
572+
std::unique_ptr<ProfileList> ProfList;
573+
569574
/// The allocator used to create AST objects.
570575
///
571576
/// AST objects are never destructed; rather, all memory associated with the
@@ -691,6 +696,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
691696
return *XRayFilter;
692697
}
693698

699+
const ProfileList &getProfileList() const { return *ProfList; }
700+
694701
DiagnosticsEngine &getDiagnostics() const;
695702

696703
FullSourceLoc getFullLoc(SourceLocation Loc) const {

clang/include/clang/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ class LangOptions : public LangOptionsBase {
285285
/// attribute(s).
286286
std::vector<std::string> XRayAttrListFiles;
287287

288+
/// Paths to special case list files specifying which entities
289+
/// (files, functions) should or should not be instrumented.
290+
std::vector<std::string> ProfileListFiles;
291+
288292
clang::ObjCRuntime ObjCRuntime;
289293

290294
CoreFoundationABI CFRuntime = CoreFoundationABI::Unspecified;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===--- ProfileList.h - ProfileList filter ---------------------*- 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+
// User-provided filters include/exclude profile instrumentation in certain
10+
// functions.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
#ifndef LLVM_CLANG_BASIC_INSTRPROFLIST_H
14+
#define LLVM_CLANG_BASIC_INSTRPROFLIST_H
15+
16+
#include "clang/Basic/CodeGenOptions.h"
17+
#include "clang/Basic/LLVM.h"
18+
#include "clang/Basic/SourceLocation.h"
19+
#include "llvm/ADT/ArrayRef.h"
20+
#include "llvm/ADT/Optional.h"
21+
#include "llvm/ADT/StringRef.h"
22+
#include <memory>
23+
24+
namespace llvm {
25+
class SpecialCaseList;
26+
}
27+
28+
namespace clang {
29+
30+
class ProfileSpecialCaseList;
31+
32+
class ProfileList {
33+
std::unique_ptr<ProfileSpecialCaseList> SCL;
34+
const bool Empty;
35+
const bool Default;
36+
SourceManager &SM;
37+
38+
public:
39+
ProfileList(ArrayRef<std::string> Paths, SourceManager &SM);
40+
~ProfileList();
41+
42+
bool isEmpty() const { return Empty; }
43+
bool getDefault() const { return Default; }
44+
45+
llvm::Optional<bool>
46+
isFunctionExcluded(StringRef FunctionName,
47+
CodeGenOptions::ProfileInstrKind Kind) const;
48+
llvm::Optional<bool>
49+
isLocationExcluded(SourceLocation Loc,
50+
CodeGenOptions::ProfileInstrKind Kind) const;
51+
llvm::Optional<bool>
52+
isFileExcluded(StringRef FileName,
53+
CodeGenOptions::ProfileInstrKind Kind) const;
54+
};
55+
56+
} // namespace clang
57+
58+
#endif

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,10 @@ defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling",
11511151
def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">,
11521152
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
11531153
HelpText<"Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">;
1154+
def fprofile_list_EQ : Joined<["-"], "fprofile-list=">,
1155+
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
1156+
HelpText<"Filename defining the list of functions/files to instrument">,
1157+
MarshallingInfoStringVector<LangOpts<"ProfileListFiles">>;
11541158

11551159
defm addrsig : BoolFOption<"addrsig",
11561160
CodeGenOpts<"Addrsig">, DefaultFalse,

clang/lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
965965
XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
966966
LangOpts.XRayNeverInstrumentFiles,
967967
LangOpts.XRayAttrListFiles, SM)),
968+
ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)),
968969
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
969970
BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM),
970971
CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),

clang/lib/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ add_clang_library(clangBasic
5959
OpenCLOptions.cpp
6060
OpenMPKinds.cpp
6161
OperatorPrecedence.cpp
62+
ProfileList.cpp
6263
SanitizerBlacklist.cpp
6364
SanitizerSpecialCaseList.cpp
6465
Sanitizers.cpp

clang/lib/Basic/ProfileList.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//===--- ProfileList.h - ProfileList filter ---------------------*- 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+
// User-provided filters include/exclude profile instrumentation in certain
10+
// functions or files.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "clang/Basic/ProfileList.h"
15+
#include "clang/Basic/FileManager.h"
16+
#include "clang/Basic/SourceManager.h"
17+
#include "llvm/Support/SpecialCaseList.h"
18+
19+
#include "llvm/Support/raw_ostream.h"
20+
21+
using namespace clang;
22+
23+
namespace clang {
24+
25+
class ProfileSpecialCaseList : public llvm::SpecialCaseList {
26+
public:
27+
static std::unique_ptr<ProfileSpecialCaseList>
28+
create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,
29+
std::string &Error);
30+
31+
static std::unique_ptr<ProfileSpecialCaseList>
32+
createOrDie(const std::vector<std::string> &Paths,
33+
llvm::vfs::FileSystem &VFS);
34+
35+
bool isEmpty() const { return Sections.empty(); }
36+
37+
bool hasPrefix(StringRef Prefix) const {
38+
for (auto &SectionIter : Sections)
39+
if (SectionIter.Entries.count(Prefix) > 0)
40+
return true;
41+
return false;
42+
}
43+
};
44+
45+
std::unique_ptr<ProfileSpecialCaseList>
46+
ProfileSpecialCaseList::create(const std::vector<std::string> &Paths,
47+
llvm::vfs::FileSystem &VFS,
48+
std::string &Error) {
49+
auto PSCL = std::make_unique<ProfileSpecialCaseList>();
50+
if (PSCL->createInternal(Paths, VFS, Error))
51+
return PSCL;
52+
return nullptr;
53+
}
54+
55+
std::unique_ptr<ProfileSpecialCaseList>
56+
ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
57+
llvm::vfs::FileSystem &VFS) {
58+
std::string Error;
59+
if (auto PSCL = create(Paths, VFS, Error))
60+
return PSCL;
61+
llvm::report_fatal_error(Error);
62+
}
63+
64+
}
65+
66+
ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM)
67+
: SCL(ProfileSpecialCaseList::createOrDie(
68+
Paths, SM.getFileManager().getVirtualFileSystem())),
69+
Empty(SCL->isEmpty()),
70+
Default(SCL->hasPrefix("fun") || SCL->hasPrefix("src")), SM(SM) {}
71+
72+
ProfileList::~ProfileList() = default;
73+
74+
static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) {
75+
switch (Kind) {
76+
case CodeGenOptions::ProfileNone:
77+
return "";
78+
case CodeGenOptions::ProfileClangInstr:
79+
return "clang";
80+
case CodeGenOptions::ProfileIRInstr:
81+
return "llvm";
82+
case CodeGenOptions::ProfileCSIRInstr:
83+
return "csllvm";
84+
}
85+
}
86+
87+
llvm::Optional<bool>
88+
ProfileList::isFunctionExcluded(StringRef FunctionName,
89+
CodeGenOptions::ProfileInstrKind Kind) const {
90+
StringRef Section = getSectionName(Kind);
91+
if (SCL->inSection(Section, "!fun", FunctionName))
92+
return true;
93+
if (SCL->inSection(Section, "fun", FunctionName))
94+
return false;
95+
return None;
96+
}
97+
98+
llvm::Optional<bool>
99+
ProfileList::isLocationExcluded(SourceLocation Loc,
100+
CodeGenOptions::ProfileInstrKind Kind) const {
101+
return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);
102+
}
103+
104+
llvm::Optional<bool>
105+
ProfileList::isFileExcluded(StringRef FileName,
106+
CodeGenOptions::ProfileInstrKind Kind) const {
107+
StringRef Section = getSectionName(Kind);
108+
if (SCL->inSection(Section, "!src", FileName))
109+
return true;
110+
if (SCL->inSection(Section, "src", FileName))
111+
return false;
112+
return None;
113+
}

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
839839
}
840840
}
841841

842+
if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone)
843+
if (CGM.isProfileInstrExcluded(Fn, Loc))
844+
Fn->addFnAttr(llvm::Attribute::NoProfile);
845+
842846
unsigned Count, Offset;
843847
if (const auto *Attr =
844848
D ? D->getAttr<PatchableFunctionEntryAttr>() : nullptr) {

0 commit comments

Comments
 (0)