[llvm] r318356 - [globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Eric Fiselier via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 18 13:05:34 PST 2017
Hi Daniel,
This broke the use of installed LLVM headers, since one of the changes adds
a `config.h` include, but `config.h` isn't an installed header.
/Eric
On Wed, Nov 15, 2017 at 5:46 PM, Daniel Sanders via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: dsanders
> Date: Wed Nov 15 16:46:35 2017
> New Revision: 318356
>
> URL: http://llvm.org/viewvc/llvm-project?rev=318356&view=rev
> Log:
> [globalisel][tablegen] Generate rule coverage and use it to identify
> untested rules
>
> Summary:
> This patch adds a LLVM_ENABLE_GISEL_COV which, like
> LLVM_ENABLE_DAGISEL_COV,
> causes TableGen to instrument the generated table to collect rule coverage
> information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
> LLVM_ENABLE_DAGISEL_COV. The information is written to files
> (${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
> concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
> read this information and use it to emit warnings about untested rules.
>
> This technique could also be used by SelectionDAG and can be further
> extended to detect hot rules and give them priority over colder rules.
>
> Usage:
> * Enable LLVM_ENABLE_GISEL_COV in CMake
> * Build the compiler and run some tests
> * cat gisel-coverage-[0-9]* > gisel-coverage-all
> * Delete lib/Target/*/*GenGlobalISel.inc*
> * Build the compiler
>
> Known issues:
> * ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
> step due to a lack of a portable 'cat' command. It should be the
> concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
> * There's no mechanism to discard coverage information when the ruleset
> changes
>
> Depends on D39742
>
> Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
>
> Reviewed By: rovka
>
> Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar,
> igorb, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D39747
>
> Added:
> llvm/trunk/include/llvm/Support/CodeGenCoverage.h
> llvm/trunk/lib/Support/CodeGenCoverage.cpp
> llvm/trunk/utils/llvm-gisel-cov.py
> Modified:
> llvm/trunk/CMakeLists.txt
> llvm/trunk/cmake/modules/TableGen.cmake
> llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
> llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
> llvm/trunk/include/llvm/Config/config.h.cmake
> llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp
> llvm/trunk/lib/Support/CMakeLists.txt
> llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
> llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
> llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
> llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp
> llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp
> llvm/trunk/test/TableGen/GlobalISelEmitter.td
> llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
>
> Modified: llvm/trunk/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/CMakeLists.
> txt?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/CMakeLists.txt (original)
> +++ llvm/trunk/CMakeLists.txt Wed Nov 15 16:46:35 2017
> @@ -167,6 +167,10 @@ if(LLVM_DEPENDENCY_DEBUGGING)
> endif()
>
> option(LLVM_ENABLE_DAGISEL_COV "Debug: Prints tablegen patterns that were
> used for selecting" OFF)
> +option(LLVM_ENABLE_GISEL_COV "Enable collection of GlobalISel rule
> coverage" OFF)
> +if(LLVM_ENABLE_GISEL_COV)
> + set(LLVM_GISEL_COV_PREFIX "${CMAKE_BINARY_DIR}/gisel-coverage-" CACHE
> STRING "Provide a filename prefix to collect the GlobalISel rule coverage")
> +endif()
>
> # Add path for custom modules
> set(CMAKE_MODULE_PATH
>
> Modified: llvm/trunk/cmake/modules/TableGen.cmake
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/
> modules/TableGen.cmake?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/cmake/modules/TableGen.cmake (original)
> +++ llvm/trunk/cmake/modules/TableGen.cmake Wed Nov 15 16:46:35 2017
> @@ -52,6 +52,13 @@ function(tablegen project ofn)
> list(APPEND LLVM_TABLEGEN_FLAGS "-instrument-coverage")
> endif()
> endif()
> + if (LLVM_ENABLE_GISEL_COV)
> + list(FIND ARGN "-gen-global-isel" idx)
> + if( NOT idx EQUAL -1 )
> + list(APPEND LLVM_TABLEGEN_FLAGS "-instrument-gisel-coverage")
> + list(APPEND LLVM_TABLEGEN_FLAGS "-gisel-coverage-file=${LLVM_
> GISEL_COV_PREFIX}all")
> + endif()
> + endif()
>
> # We need both _TABLEGEN_TARGET and _TABLEGEN_EXE in the DEPENDS list
> # (both the target and the file) to have .inc files rebuilt on
>
> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/CodeGen/GlobalISel/InstructionSelector.h?rev=
> 318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
> (original)
> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h Wed
> Nov 15 16:46:35 2017
> @@ -17,8 +17,9 @@
> #define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
>
> #include "llvm/ADT/DenseMap.h"
> -#include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/Optional.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/Support/CodeGenCoverage.h"
> #include <bitset>
> #include <cstddef>
> #include <cstdint>
> @@ -33,6 +34,7 @@ class APFloat;
> class LLT;
> class MachineInstr;
> class MachineInstrBuilder;
> +class MachineFunction;
> class MachineOperand;
> class MachineRegisterInfo;
> class RegisterBankInfo;
> @@ -262,6 +264,10 @@ enum {
>
> /// A successful emission
> GIR_Done,
> +
> + /// Increment the rule coverage counter.
> + /// - RuleID - The ID of the rule that was covered.
> + GIR_Coverage,
> };
>
> enum {
> @@ -289,7 +295,7 @@ public:
> /// if returns true:
> /// for I in all mutated/inserted instructions:
> /// !isPreISelGenericOpcode(I.getOpcode())
> - virtual bool select(MachineInstr &I) const = 0;
> + virtual bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo)
> const = 0;
>
> protected:
> using ComplexRendererFns =
> @@ -328,8 +334,8 @@ protected:
> const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn>
> &MatcherInfo,
> const int64_t *MatchTable, const TargetInstrInfo &TII,
> MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
> - const RegisterBankInfo &RBI,
> - const PredicateBitset &AvailableFeatures) const;
> + const RegisterBankInfo &RBI, const PredicateBitset
> &AvailableFeatures,
> + CodeGenCoverage &CoverageInfo) const;
>
> /// Constrain a register operand of an instruction \p I to a specified
> /// register class. This could involve inserting COPYs before (for
> uses) or
>
> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/
> InstructionSelectorImpl.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h?rev=
> 318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
> (original)
> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
> Wed Nov 15 16:46:35 2017
> @@ -49,8 +49,8 @@ bool InstructionSelector::executeMatchTa
> const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn>
> &MatcherInfo,
> const int64_t *MatchTable, const TargetInstrInfo &TII,
> MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
> - const RegisterBankInfo &RBI,
> - const PredicateBitset &AvailableFeatures) const {
> + const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
> + CodeGenCoverage &CoverageInfo) const {
> uint64_t CurrentIdx = 0;
> SmallVector<uint64_t, 8> OnFailResumeAt;
>
> @@ -677,6 +677,16 @@ bool InstructionSelector::executeMatchTa
> break;
> }
>
> + case GIR_Coverage: {
> + int64_t RuleID = MatchTable[CurrentIdx++];
> + CoverageInfo.setCovered(RuleID);
> +
> + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
> + dbgs()
> + << CurrentIdx << ": GIR_Coverage(" << RuleID <<
> ")");
> + break;
> + }
> +
> case GIR_Done:
> DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
> dbgs() << CurrentIdx << ": GIR_Done");
>
> Modified: llvm/trunk/include/llvm/Config/config.h.cmake
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/Config/config.h.cmake?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/Config/config.h.cmake (original)
> +++ llvm/trunk/include/llvm/Config/config.h.cmake Wed Nov 15 16:46:35 2017
> @@ -437,4 +437,10 @@
> /* Define to a function implementing strdup */
> #cmakedefine strdup ${strdup}
>
> +/* Whether GlobalISel rule coverage is being collected */
> +#cmakedefine01 LLVM_GISEL_COV_ENABLED
> +
> +/* Define to the default GlobalISel coverage file prefix */
> +#cmakedefine LLVM_GISEL_COV_PREFIX "${LLVM_GISEL_COV_PREFIX}"
> +
> #endif
>
> Added: llvm/trunk/include/llvm/Support/CodeGenCoverage.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/Support/CodeGenCoverage.h?rev=318356&view=auto
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/Support/CodeGenCoverage.h (added)
> +++ llvm/trunk/include/llvm/Support/CodeGenCoverage.h Wed Nov 15 16:46:35
> 2017
> @@ -0,0 +1,37 @@
> +//== llvm/Support/CodeGenCoverage.h ------------------------------*- C++
> -*-==//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +/// \file This file provides rule coverage tracking for tablegen-erated
> CodeGen.
> +//===------------------------------------------------------
> ----------------===//
> +
> +#ifndef LLVM_SUPPORT_CODEGENCOVERAGE_H
> +#define LLVM_SUPPORT_CODEGENCOVERAGE_H
> +
> +#include "llvm/ADT/BitVector.h"
> +#include "llvm/Config/config.h"
> +
> +namespace llvm {
> +class LLVMContext;
> +
> +class CodeGenCoverage {
> +protected:
> + BitVector RuleCoverage;
> +
> +public:
> + CodeGenCoverage();
> +
> + void setCovered(uint64_t RuleID);
> + bool isCovered(uint64_t RuleID);
> +
> + bool parse(MemoryBuffer &Buffer, StringRef BackendName);
> + bool emit(StringRef FilePrefix, StringRef BackendName) const;
> + void reset();
> +};
> +} // end namespace llvm
> +
> +#endif // ifndef LLVM_SUPPORT_CODEGENCOVERAGE_H
>
> Modified: llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> CodeGen/GlobalISel/InstructionSelect.cpp?rev=318356&r1=318355&r2=318356&
> view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp (original)
> +++ llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp Wed Nov 15
> 16:46:35 2017
> @@ -20,10 +20,12 @@
> #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
> #include "llvm/CodeGen/MachineRegisterInfo.h"
> #include "llvm/CodeGen/TargetPassConfig.h"
> +#include "llvm/Config/config.h"
> #include "llvm/IR/Constants.h"
> #include "llvm/IR/Function.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/Debug.h"
> +#include "llvm/Support/TargetRegistry.h"
> #include "llvm/Target/TargetLowering.h"
> #include "llvm/Target/TargetSubtargetInfo.h"
>
> @@ -31,6 +33,15 @@
>
> using namespace llvm;
>
> +#ifdef LLVM_GISEL_COV_PREFIX
> +static cl::opt<std::string>
> + CoveragePrefix("gisel-coverage-prefix", cl::init(LLVM_GISEL_COV_
> PREFIX),
> + cl::desc("Record GlobalISel rule coverage files of
> this "
> + "prefix if instrumentation was generated"));
> +#else
> +static const std::string CoveragePrefix = "";
> +#endif
> +
> char InstructionSelect::ID = 0;
> INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,
> "Select target instructions out of generic
> instructions",
> @@ -66,6 +77,7 @@ bool InstructionSelect::runOnMachineFunc
>
> const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
> const InstructionSelector *ISel = MF.getSubtarget().
> getInstructionSelector();
> + CodeGenCoverage CoverageInfo;
> assert(ISel && "Cannot work without InstructionSelector");
>
> // An optimization remark emitter. Used to report failures.
> @@ -127,7 +139,7 @@ bool InstructionSelect::runOnMachineFunc
> continue;
> }
>
> - if (!ISel->select(MI)) {
> + if (!ISel->select(MI, CoverageInfo)) {
> // FIXME: It would be nice to dump all inserted instructions.
> It's
> // not obvious how, esp. considering select() can insert after MI.
> reportGISelFailure(MF, TPC, MORE, "gisel-select", "cannot
> select", MI);
> @@ -187,6 +199,13 @@ bool InstructionSelect::runOnMachineFunc
> auto &TLI = *MF.getSubtarget().getTargetLowering();
> TLI.finalizeLowering(MF);
>
> + CoverageInfo.emit(CoveragePrefix,
> + MF.getSubtarget()
> + .getTargetLowering()
> + ->getTargetMachine()
> + .getTarget()
> + .getBackendName());
> +
> // FIXME: Should we accurately track changes?
> return true;
> }
>
> Modified: llvm/trunk/lib/Support/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Support/CMakeLists.txt?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Support/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Support/CMakeLists.txt Wed Nov 15 16:46:35 2017
> @@ -48,6 +48,7 @@ add_llvm_library(LLVMSupport
> circular_raw_ostream.cpp
> Chrono.cpp
> COM.cpp
> + CodeGenCoverage.cpp
> CommandLine.cpp
> Compression.cpp
> ConvertUTF.cpp
>
> Added: llvm/trunk/lib/Support/CodeGenCoverage.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Support/CodeGenCoverage.cpp?rev=318356&view=auto
> ============================================================
> ==================
> --- llvm/trunk/lib/Support/CodeGenCoverage.cpp (added)
> +++ llvm/trunk/lib/Support/CodeGenCoverage.cpp Wed Nov 15 16:46:35 2017
> @@ -0,0 +1,118 @@
> +//===- lib/Support/CodeGenCoverage.cpp ------------------------------
> -------==//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +/// \file
> +/// This file implements the CodeGenCoverage class.
> +//===------------------------------------------------------
> ----------------===//
> +
> +#include "llvm/Support/CodeGenCoverage.h"
> +
> +#include "llvm/Support/Endian.h"
> +#include "llvm/Support/FileSystem.h"
> +#include "llvm/Support/Mutex.h"
> +#include "llvm/Support/ScopedPrinter.h"
> +#include "llvm/Support/ToolOutputFile.h"
> +
> +#if LLVM_ON_UNIX
> +#include <unistd.h>
> +#elif LLVM_ON_WIN32
> +#include <windows.h>
> +#endif
> +
> +using namespace llvm;
> +
> +static sys::SmartMutex<true> OutputMutex;
> +
> +CodeGenCoverage::CodeGenCoverage() {}
> +
> +void CodeGenCoverage::setCovered(uint64_t RuleID) {
> + if (RuleCoverage.size() <= RuleID)
> + RuleCoverage.resize(RuleID + 1, 0);
> + RuleCoverage[RuleID] = true;
> +}
> +
> +bool CodeGenCoverage::isCovered(uint64_t RuleID) {
> + if (RuleCoverage.size() <= RuleID)
> + return false;
> + return RuleCoverage[RuleID];
> +}
> +
> +bool CodeGenCoverage::parse(MemoryBuffer &Buffer, StringRef BackendName)
> {
> + const char *CurPtr = Buffer.getBufferStart();
> +
> + while (CurPtr != Buffer.getBufferEnd()) {
> + // Read the backend name from the input.
> + const char *LexedBackendName = CurPtr;
> + while (*CurPtr++ != 0)
> + ;
> + if (CurPtr == Buffer.getBufferEnd())
> + return false; // Data is invalid, expected rule id's to follow.
> +
> + bool IsForThisBackend = BackendName.equals(LexedBackendName);
> + while (CurPtr != Buffer.getBufferEnd()) {
> + if (std::distance(CurPtr, Buffer.getBufferEnd()) < 8)
> + return false; // Data is invalid. Not enough bytes for another
> rule id.
> +
> + uint64_t RuleID = support::endian::read64(CurPtr, support::native);
> + CurPtr += 8;
> +
> + // ~0ull terminates the rule id list.
> + if (RuleID == ~0ull)
> + break;
> +
> + // Anything else, is recorded or ignored depending on whether it's
> + // intended for the backend we're interested in.
> + if (IsForThisBackend)
> + setCovered(RuleID);
> + }
> + }
> +
> + return true;
> +}
> +
> +bool CodeGenCoverage::emit(StringRef CoveragePrefix,
> + StringRef BackendName) const {
> + if (!CoveragePrefix.empty() && !RuleCoverage.empty()) {
> + sys::SmartScopedLock<true> Lock(OutputMutex);
> +
> + // We can handle locking within a process easily enough but we don't
> want to
> + // manage it between multiple processes. Use the process ID to ensure
> no
> + // more than one process is ever writing to the same file at the same
> time.
> + std::string Pid =
> +#if LLVM_ON_UNIX
> + llvm::to_string(::getpid());
> +#elif LLVM_ON_WIN32
> + llvm::to_string(::GetCurrentProcessId());
> +#else
> + "";
> +#endif
> +
> + std::string CoverageFilename = (CoveragePrefix + Pid).str();
> +
> + std::error_code EC;
> + sys::fs::OpenFlags OpenFlags = sys::fs::F_Append;
> + std::unique_ptr<ToolOutputFile> CoverageFile =
> + llvm::make_unique<ToolOutputFile>(CoverageFilename, EC,
> OpenFlags);
> + if (EC)
> + return false;
> +
> + uint64_t Zero = 0;
> + uint64_t InvZero = ~0ull;
> + CoverageFile->os() << BackendName;
> + CoverageFile->os().write((const char *)&Zero, sizeof(unsigned char));
> + for (uint64_t I : RuleCoverage.set_bits())
> + CoverageFile->os().write((const char *)&I, sizeof(uint64_t));
> + CoverageFile->os().write((const char *)&InvZero, sizeof(uint64_t));
> +
> + CoverageFile->keep();
> + }
> +
> + return true;
> +}
> +
> +void CodeGenCoverage::reset() { RuleCoverage.resize(0); }
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/
> AArch64InstructionSelector.cpp?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
> (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Wed Nov
> 15 16:46:35 2017
> @@ -48,13 +48,13 @@ public:
> const AArch64Subtarget &STI,
> const AArch64RegisterBankInfo &RBI);
>
> - bool select(MachineInstr &I) const override;
> + bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const
> override;
> static const char *getName() { return DEBUG_TYPE; }
>
> private:
> /// tblgen-erated 'select' implementation, used as the initial selector
> for
> /// the patterns that don't require complex C++.
> - bool selectImpl(MachineInstr &I) const;
> + bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
>
> bool selectVaStartAAPCS(MachineInstr &I, MachineFunction &MF,
> MachineRegisterInfo &MRI) const;
> @@ -609,7 +609,8 @@ bool AArch64InstructionSelector::selectV
> return true;
> }
>
> -bool AArch64InstructionSelector::select(MachineInstr &I) const {
> +bool AArch64InstructionSelector::select(MachineInstr &I,
> + CodeGenCoverage &CoverageInfo)
> const {
> assert(I.getParent() && "Instruction should be in a basic block!");
> assert(I.getParent()->getParent() && "Instruction should be in a
> function!");
>
> @@ -667,7 +668,7 @@ bool AArch64InstructionSelector::select(
> return false;
> }
>
> - if (selectImpl(I))
> + if (selectImpl(I, CoverageInfo))
> return true;
>
> LLT Ty =
>
> Modified: llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/
> AMDGPUInstructionSelector.cpp?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp (original)
> +++ llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp Wed Nov 15
> 16:46:35 2017
> @@ -402,7 +402,8 @@ bool AMDGPUInstructionSelector::selectG_
> return Ret;
> }
>
> -bool AMDGPUInstructionSelector::select(MachineInstr &I) const {
> +bool AMDGPUInstructionSelector::select(MachineInstr &I,
> + CodeGenCoverage &CoverageInfo)
> const {
>
> if (!isPreISelGenericOpcode(I.getOpcode()))
> return true;
>
> Modified: llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/
> AMDGPUInstructionSelector.h?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.h (original)
> +++ llvm/trunk/lib/Target/AMDGPU/AMDGPUInstructionSelector.h Wed Nov 15
> 16:46:35 2017
> @@ -35,7 +35,8 @@ public:
> AMDGPUInstructionSelector(const SISubtarget &STI,
> const AMDGPURegisterBankInfo &RBI);
>
> - bool select(MachineInstr &I) const override;
> + bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const
> override;
> +
> private:
> struct GEPInfo {
> const MachineInstr &GEP;
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/
> ARM/ARMInstructionSelector.cpp?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp Wed Nov 15
> 16:46:35 2017
> @@ -35,11 +35,11 @@ public:
> ARMInstructionSelector(const ARMBaseTargetMachine &TM, const
> ARMSubtarget &STI,
> const ARMRegisterBankInfo &RBI);
>
> - bool select(MachineInstr &I) const override;
> + bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const
> override;
> static const char *getName() { return DEBUG_TYPE; }
>
> private:
> - bool selectImpl(MachineInstr &I) const;
> + bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
>
> struct CmpConstants;
> struct InsertInfo;
> @@ -653,7 +653,8 @@ bool ARMInstructionSelector::selectShift
> return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
> }
>
> -bool ARMInstructionSelector::select(MachineInstr &I) const {
> +bool ARMInstructionSelector::select(MachineInstr &I,
> + CodeGenCoverage &CoverageInfo) const {
> assert(I.getParent() && "Instruction should be in a basic block!");
> assert(I.getParent()->getParent() && "Instruction should be in a
> function!");
>
> @@ -668,7 +669,7 @@ bool ARMInstructionSelector::select(Mach
> return true;
> }
>
> - if (selectImpl(I))
> + if (selectImpl(I, CoverageInfo))
> return true;
>
> MachineInstrBuilder MIB{MF, I};
>
> Modified: llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/
> X86/X86InstructionSelector.cpp?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp Wed Nov 15
> 16:46:35 2017
> @@ -61,13 +61,13 @@ public:
> X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget
> &STI,
> const X86RegisterBankInfo &RBI);
>
> - bool select(MachineInstr &I) const override;
> + bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const
> override;
> static const char *getName() { return DEBUG_TYPE; }
>
> private:
> /// tblgen-erated 'select' implementation, used as the initial selector
> for
> /// the patterns that don't require complex C++.
> - bool selectImpl(MachineInstr &I) const;
> + bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
>
> // TODO: remove after supported by Tablegen-erated instruction
> selection.
> unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned
> Opc,
> @@ -93,9 +93,11 @@ private:
> MachineFunction &MF) const;
> bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
> bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
> - MachineFunction &MF) const;
> + MachineFunction &MF,
> + CodeGenCoverage &CoverageInfo) const;
> bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
> - MachineFunction &MF) const;
> + MachineFunction &MF,
> + CodeGenCoverage &CoverageInfo) const;
> bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
> MachineFunction &MF) const;
> bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
> @@ -294,7 +296,8 @@ bool X86InstructionSelector::selectCopy(
> return true;
> }
>
> -bool X86InstructionSelector::select(MachineInstr &I) const {
> +bool X86InstructionSelector::select(MachineInstr &I,
> + CodeGenCoverage &CoverageInfo) const {
> assert(I.getParent() && "Instruction should be in a basic block!");
> assert(I.getParent()->getParent() && "Instruction should be in a
> function!");
>
> @@ -318,7 +321,7 @@ bool X86InstructionSelector::select(Mach
> assert(I.getNumOperands() == I.getNumExplicitOperands() &&
> "Generic instruction has unexpected implicit operands\n");
>
> - if (selectImpl(I))
> + if (selectImpl(I, CoverageInfo))
> return true;
>
> DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
> @@ -350,9 +353,9 @@ bool X86InstructionSelector::select(Mach
> case TargetOpcode::G_UADDE:
> return selectUadde(I, MRI, MF);
> case TargetOpcode::G_UNMERGE_VALUES:
> - return selectUnmergeValues(I, MRI, MF);
> + return selectUnmergeValues(I, MRI, MF, CoverageInfo);
> case TargetOpcode::G_MERGE_VALUES:
> - return selectMergeValues(I, MRI, MF);
> + return selectMergeValues(I, MRI, MF, CoverageInfo);
> case TargetOpcode::G_EXTRACT:
> return selectExtract(I, MRI, MF);
> case TargetOpcode::G_INSERT:
> @@ -1093,9 +1096,9 @@ bool X86InstructionSelector::selectInser
> return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
> }
>
> -bool X86InstructionSelector::selectUnmergeValues(MachineInstr &I,
> - MachineRegisterInfo &MRI,
> - MachineFunction &MF)
> const {
> +bool X86InstructionSelector::selectUnmergeValues(
> + MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF,
> + CodeGenCoverage &CoverageInfo) const {
> assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&
> "unexpected instruction");
>
> @@ -1111,7 +1114,7 @@ bool X86InstructionSelector::selectUnmer
> .addReg(SrcReg)
> .addImm(Idx * DefSize);
>
> - if (!select(ExtrInst))
> + if (!select(ExtrInst, CoverageInfo))
> return false;
> }
>
> @@ -1119,9 +1122,9 @@ bool X86InstructionSelector::selectUnmer
> return true;
> }
>
> -bool X86InstructionSelector::selectMergeValues(MachineInstr &I,
> - MachineRegisterInfo &MRI,
> - MachineFunction &MF) const
> {
> +bool X86InstructionSelector::selectMergeValues(
> + MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF,
> + CodeGenCoverage &CoverageInfo) const {
> assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES) &&
> "unexpected instruction");
>
> @@ -1153,7 +1156,7 @@ bool X86InstructionSelector::selectMerge
>
> DefReg = Tmp;
>
> - if (!select(InsertInst))
> + if (!select(InsertInst, CoverageInfo))
> return false;
> }
>
> @@ -1161,7 +1164,7 @@ bool X86InstructionSelector::selectMerge
> TII.get(TargetOpcode::COPY), DstReg)
> .addReg(DefReg);
>
> - if (!select(CopyInst))
> + if (!select(CopyInst, CoverageInfo))
> return false;
>
> I.eraseFromParent();
>
> Modified: llvm/trunk/test/TableGen/GlobalISelEmitter.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> TableGen/GlobalISelEmitter.td?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/TableGen/GlobalISelEmitter.td (original)
> +++ llvm/trunk/test/TableGen/GlobalISelEmitter.td Wed Nov 15 16:46:35 2017
> @@ -153,7 +153,7 @@ def HasC : Predicate<"Subtarget->hasC()"
> // CHECK-NEXT: &MyTargetInstructionSelector::selectComplexPatternRR,
> // gi_complex_rr
> // CHECK-NEXT: }
>
> -// CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I)
> const {
> +// CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I,
> CodeGenCoverage &CoverageInfo) const {
> // CHECK-NEXT: MachineFunction &MF = *I.getParent()->getParent();
> // CHECK-NEXT: MachineRegisterInfo &MRI = MF.getRegInfo();
> // CHECK: AvailableFunctionFeatures = computeAvailableFunctionFeatures(&STI,
> &MF);
> @@ -899,6 +899,6 @@ def BR : I<(outs), (ins unknown:$target)
>
> // CHECK-NEXT: GIM_Reject,
> // CHECK-NEXT: };
> -// CHECK-NEXT: if (executeMatchTable(*this, OutMIs, State, MatcherInfo,
> MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures)) {
> +// CHECK-NEXT: if (executeMatchTable(*this, OutMIs, State, MatcherInfo,
> MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo)) {
> // CHECK-NEXT: return true;
> // CHECK-NEXT: }
>
> Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/
> TableGen/GlobalISelEmitter.cpp?rev=318356&r1=318355&r2=318356&view=diff
> ============================================================
> ==================
> --- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Wed Nov 15 16:46:35
> 2017
> @@ -36,6 +36,7 @@
> #include "llvm/ADT/SmallSet.h"
> #include "llvm/ADT/Statistic.h"
> #include "llvm/CodeGen/MachineValueType.h"
> +#include "llvm/Support/CodeGenCoverage.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/Error.h"
> #include "llvm/Support/LowLevelTypeImpl.h"
> @@ -43,8 +44,8 @@
> #include "llvm/TableGen/Error.h"
> #include "llvm/TableGen/Record.h"
> #include "llvm/TableGen/TableGenBackend.h"
> -#include <string>
> #include <numeric>
> +#include <string>
> using namespace llvm;
>
> #define DEBUG_TYPE "gisel-emitter"
> @@ -52,6 +53,7 @@ using namespace llvm;
> STATISTIC(NumPatternTotal, "Total number of patterns");
> STATISTIC(NumPatternImported, "Number of patterns imported from
> SelectionDAG");
> STATISTIC(NumPatternImportsSkipped, "Number of SelectionDAG imports
> skipped");
> +STATISTIC(NumPatternsTested, "Number of patterns executed according to
> coverage information");
> STATISTIC(NumPatternEmitted, "Number of patterns emitted");
>
> cl::OptionCategory GlobalISelEmitterCat("Options for -gen-global-isel");
> @@ -62,6 +64,16 @@ static cl::opt<bool> WarnOnSkippedPatter
> "in the GlobalISel selector"),
> cl::init(false), cl::cat(GlobalISelEmitterCat));
>
> +static cl::opt<bool> GenerateCoverage(
> + "instrument-gisel-coverage",
> + cl::desc("Generate coverage instrumentation for GlobalISel"),
> + cl::init(false), cl::cat(GlobalISelEmitterCat));
> +
> +static cl::opt<std::string> UseCoverageFile(
> + "gisel-coverage-file", cl::init(""),
> + cl::desc("Specify file to retrieve coverage information from"),
> + cl::cat(GlobalISelEmitterCat));
> +
> namespace {
> //===- Helper functions ------------------------------
> ---------------------===//
>
> @@ -569,14 +581,20 @@ protected:
> /// A map of Symbolic Names to ComplexPattern sub-operands.
> DefinedComplexPatternSubOperandMap ComplexSubOperands;
>
> + uint64_t RuleID;
> + static uint64_t NextRuleID;
> +
> public:
> RuleMatcher(ArrayRef<SMLoc> SrcLoc)
> : Matchers(), Actions(), InsnVariableIDs(), MutatableInsns(),
> DefinedOperands(), NextInsnVarID(0), NextOutputInsnID(0),
> - NextTempRegID(0), SrcLoc(SrcLoc), ComplexSubOperands() {}
> + NextTempRegID(0), SrcLoc(SrcLoc), ComplexSubOperands(),
> + RuleID(NextRuleID++) {}
> RuleMatcher(RuleMatcher &&Other) = default;
> RuleMatcher &operator=(RuleMatcher &&Other) = default;
>
> + uint64_t getRuleID() const { return RuleID; }
> +
> InstructionMatcher &addInstructionMatcher(StringRef SymbolicName);
> void addRequiredFeature(Record *Feature);
> const std::vector<Record *> &getRequiredFeatures() const;
> @@ -664,6 +682,8 @@ public:
> unsigned allocateTempRegID() { return NextTempRegID++; }
> };
>
> +uint64_t RuleMatcher::NextRuleID = 0;
> +
> using action_iterator = RuleMatcher::action_iterator;
>
> template <class PredicateTy> class PredicateListMatcher {
> @@ -2204,6 +2224,11 @@ void RuleMatcher::emit(MatchTable &Table
>
> for (const auto &MA : Actions)
> MA->emitActionOpcodes(Table, *this);
> +
> + if (GenerateCoverage)
> + Table << MatchTable::Opcode("GIR_Coverage") <<
> MatchTable::IntValue(RuleID)
> + << MatchTable::LineBreak;
> +
> Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak
> << MatchTable::Label(LabelID);
> }
> @@ -2309,6 +2334,9 @@ private:
> // Map of predicates to their subtarget features.
> SubtargetFeatureInfoMap SubtargetFeatures;
>
> + // Rule coverage information.
> + Optional<CodeGenCoverage> RuleCoverage;
> +
> void gatherNodeEquivs();
> Record *findNodeEquiv(Record *N) const;
>
> @@ -3227,6 +3255,20 @@ void GlobalISelEmitter::emitImmPredicate
> }
>
> void GlobalISelEmitter::run(raw_ostream &OS) {
> + if (!UseCoverageFile.empty()) {
> + RuleCoverage = CodeGenCoverage();
> + auto RuleCoverageBufOrErr = MemoryBuffer::getFile(UseCoverageFile);
> + if (!RuleCoverageBufOrErr) {
> + PrintWarning(SMLoc(), "Missing rule coverage data");
> + RuleCoverage = None;
> + } else {
> + if (!RuleCoverage->parse(*RuleCoverageBufOrErr.get(),
> Target.getName())) {
> + PrintWarning(SMLoc(), "Ignoring invalid or missing rule coverage
> data");
> + RuleCoverage = None;
> + }
> + }
> + }
> +
> // Track the GINodeEquiv definitions.
> gatherNodeEquivs();
>
> @@ -3252,6 +3294,13 @@ void GlobalISelEmitter::run(raw_ostream
> continue;
> }
>
> + if (RuleCoverage) {
> + if (RuleCoverage->isCovered(MatcherOrErr->getRuleID()))
> + ++NumPatternsTested;
> + else
> + PrintWarning(Pat.getSrcRecord()->getLoc(),
> + "Pattern is not covered by a test");
> + }
> Rules.push_back(std::move(MatcherOrErr.get()));
> }
>
> @@ -3431,7 +3480,8 @@ void GlobalISelEmitter::run(raw_ostream
> OS << "};\n\n";
>
> OS << "bool " << Target.getName()
> - << "InstructionSelector::selectImpl(MachineInstr &I) const {\n"
> + << "InstructionSelector::selectImpl(MachineInstr &I,
> CodeGenCoverage "
> + "&CoverageInfo) const {\n"
> << " MachineFunction &MF = *I.getParent()->getParent();\n"
> << " MachineRegisterInfo &MRI = MF.getRegInfo();\n"
> << " // FIXME: This should be computed on a per-function basis
> rather "
> @@ -3452,7 +3502,7 @@ void GlobalISelEmitter::run(raw_ostream
> Table.emitDeclaration(OS);
> OS << " if (executeMatchTable(*this, OutMIs, State, MatcherInfo, ";
> Table.emitUse(OS);
> - OS << ", TII, MRI, TRI, RBI, AvailableFeatures)) {\n"
> + OS << ", TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo)) {\n"
> << " return true;\n"
> << " }\n\n";
>
>
> Added: llvm/trunk/utils/llvm-gisel-cov.py
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/llvm-
> gisel-cov.py?rev=318356&view=auto
> ============================================================
> ==================
> --- llvm/trunk/utils/llvm-gisel-cov.py (added)
> +++ llvm/trunk/utils/llvm-gisel-cov.py Wed Nov 15 16:46:35 2017
> @@ -0,0 +1,67 @@
> +#!/usr/bin/env python
> +"""
> +Summarize the information in the given coverage files.
> +
> +Emits the number of rules covered or the percentage of rules covered
> depending
> +on whether --num-rules has been used to specify the total number of rules.
> +"""
> +
> +import argparse
> +import struct
> +
> +class FileFormatError(Exception):
> + pass
> +
> +def backend_int_pair(s):
> + backend, sep, value = s.partition('=')
> + if (sep is None):
> + raise argparse.ArgumentTypeError("'=' missing, expected name=value")
> + if (not backend):
> + raise argparse.ArgumentTypeError("Expected name=value")
> + if (not value):
> + raise argparse.ArgumentTypeError("Expected name=value")
> + return backend, int(value)
> +
> +def main():
> + parser = argparse.ArgumentParser(description=__doc__)
> + parser.add_argument('input', nargs='+')
> + parser.add_argument('--num-rules', type=backend_int_pair,
> action='append',
> + metavar='BACKEND=NUM',
> + help='Specify the number of rules for a backend')
> + args = parser.parse_args()
> +
> + covered_rules = {}
> +
> + for input_filename in args.input:
> + with open(input_filename, 'rb') as input_fh:
> + data = input_fh.read()
> + pos = 0
> + while data:
> + backend, _, data = data.partition('\0')
> + pos += len(backend)
> + pos += 1
> +
> + if len(backend) == 0:
> + raise FileFormatError()
> + backend, = struct.unpack("%ds" % len(backend), backend)
> +
> + while data:
> + if len(data) < 8:
> + raise FileFormatError()
> + rule_id, = struct.unpack("Q", data[:8])
> + pos += 8
> + data = data[8:]
> + if rule_id == (2 ** 64) - 1:
> + break
> + covered_rules[backend] = covered_rules.get(backend, {})
> + covered_rules[backend][rule_id] = covered_rules[backend].get(rule_id,
> 0) + 1
> +
> + num_rules = dict(args.num_rules)
> + for backend, rules_for_backend in covered_rules.items():
> + if backend in num_rules:
> + print "%s: %3.2f%% of rules covered" % (backend,
> (float(len(rules_for_backend.keys())) / num_rules[backend]) * 100)
> + else:
> + print "%s: %d rules covered" % (backend,
> len(rules_for_backend.keys()))
> +
> +if __name__ == '__main__':
> + main()
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171118/b0d7ab4e/attachment.html>
More information about the llvm-commits
mailing list