<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>