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