Commit bb9eb198 authored by Petr Hosek's avatar Petr Hosek
Browse files

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
parent fc319202
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2045,6 +2045,12 @@ Set update method of profile counters (atomic,prefer-atomic,single)

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

.. program:: clang1
.. option:: -fprofile-list=<file>
.. program:: clang

Filename defining the list of functions/files to instrument. The file uses the sanitizer special case list format.

.. option:: -freciprocal-math, -fno-reciprocal-math

Allow division operations to be reassociated
+59 −0
Original line number Diff line number Diff line
@@ -2282,6 +2282,63 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or
Note that these flags should appear after the corresponding profile
flags to have an effect.

Instrumenting only selected files or functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Sometimes it's useful to only instrument certain files or functions.  For
example in automated testing infrastructure, it may be desirable to only
instrument files or functions that were modified by a patch to reduce the
overhead of instrumenting a full system.

This can be done using the ``-fprofile-list`` option.

.. option:: -fprofile-list=<pathname>

  This option can be used to apply profile instrumentation only to selected
  files or functions. ``pathname`` should point to a file in the
  :doc:`SanitizerSpecialCaseList` format which selects which files and
  functions to instrument.

  .. code-block:: console

    $ echo "fun:test" > fun.list
    $ clang++ -O2 -fprofile-instr-generate -fprofile-list=fun.list code.cc -o code

The option can be specified multiple times to pass multiple files.

.. code-block:: console

    $ echo "!fun:*test*" > fun.list
    $ echo "src:code.cc" > src.list
    % clang++ -O2 -fprofile-instr-generate -fcoverage-mapping -fprofile-list=fun.list -fprofile-list=code.list code.cc -o code

To filter individual functions or entire source files using ``fun:<name>`` or
``src:<file>`` respectively. To exclude a function or a source file, use
``!fun:<name>`` or ``!src:<file>`` respectively. The format also supports
wildcard expansion. The compiler generated functions are assumed to be located
in the main source file.  It is also possible to restrict the filter to a
particular instrumentation type by using a named section.

.. code-block:: none

  # all functions whose name starts with foo will be instrumented.
  fun:foo*

  # except for foo1 which will be excluded from instrumentation.
  !fun:foo1

  # every function in path/to/foo.cc will be instrumented.
  src:path/to/foo.cc

  # bar will be instrumented only when using backend instrumentation.
  # Recognized section names are clang, llvm and csllvm.
  [llvm]
  fun:bar

When the file contains only excludes, all files and functions except for the
excluded ones will be instrumented. Otherwise, only the files and functions
specified will be instrumented.

Profile remapping
^^^^^^^^^^^^^^^^^

@@ -3740,6 +3797,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
                              Use instrumentation data for profile-guided optimization
      -fprofile-remapping-file=<file>
                              Use the remappings described in <file> to match the profile data against names in the program
      -fprofile-list=<file>
                              Filename defining the list of functions/files to instrument
      -fsanitize-address-field-padding=<value>
                              Level of field padding for AddressSanitizer
      -fsanitize-address-globals-dead-stripping
+7 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "clang/Basic/Linkage.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/ProfileList.h"
#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
@@ -566,6 +567,10 @@ private:
  /// should be imbued with the XRay "always" or "never" attributes.
  std::unique_ptr<XRayFunctionFilter> XRayFilter;

  /// ProfileList object that is used by the profile instrumentation
  /// to decide which entities should be instrumented.
  std::unique_ptr<ProfileList> ProfList;

  /// The allocator used to create AST objects.
  ///
  /// AST objects are never destructed; rather, all memory associated with the
@@ -691,6 +696,8 @@ public:
    return *XRayFilter;
  }

  const ProfileList &getProfileList() const { return *ProfList; }

  DiagnosticsEngine &getDiagnostics() const;

  FullSourceLoc getFullLoc(SourceLocation Loc) const {
+4 −0
Original line number Diff line number Diff line
@@ -285,6 +285,10 @@ public:
  /// attribute(s).
  std::vector<std::string> XRayAttrListFiles;

  /// Paths to special case list files specifying which entities
  /// (files, functions) should or should not be instrumented.
  std::vector<std::string> ProfileListFiles;

  clang::ObjCRuntime ObjCRuntime;

  CoreFoundationABI CFRuntime = CoreFoundationABI::Unspecified;
+58 −0
Original line number Diff line number Diff line
//===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// User-provided filters include/exclude profile instrumentation in certain
// functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_INSTRPROFLIST_H
#define LLVM_CLANG_BASIC_INSTRPROFLIST_H

#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include <memory>

namespace llvm {
class SpecialCaseList;
}

namespace clang {

class ProfileSpecialCaseList;

class ProfileList {
  std::unique_ptr<ProfileSpecialCaseList> SCL;
  const bool Empty;
  const bool Default;
  SourceManager &SM;

public:
  ProfileList(ArrayRef<std::string> Paths, SourceManager &SM);
  ~ProfileList();

  bool isEmpty() const { return Empty; }
  bool getDefault() const { return Default; }

  llvm::Optional<bool>
  isFunctionExcluded(StringRef FunctionName,
                     CodeGenOptions::ProfileInstrKind Kind) const;
  llvm::Optional<bool>
  isLocationExcluded(SourceLocation Loc,
                     CodeGenOptions::ProfileInstrKind Kind) const;
  llvm::Optional<bool>
  isFileExcluded(StringRef FileName,
                 CodeGenOptions::ProfileInstrKind Kind) const;
};

} // namespace clang

#endif
Loading