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