Expand Up
@@ -36,22 +36,24 @@
#include " llvm/ADT/SmallSet.h"
#include " llvm/ADT/Statistic.h"
#include " llvm/CodeGen/MachineValueType.h"
#include " llvm/Support/CodeGenCoverage.h"
#include " llvm/Support/CommandLine.h"
#include " llvm/Support/Error.h"
#include " llvm/Support/LowLevelTypeImpl.h"
#include " llvm/Support/ScopedPrinter.h"
#include " llvm/TableGen/Error.h"
#include " llvm/TableGen/Record.h"
#include " llvm/TableGen/TableGenBackend.h"
#include < string>
#include < numeric>
#include < string>
using namespace llvm ;
#define DEBUG_TYPE " gisel-emitter"
STATISTIC (NumPatternTotal, " Total number of patterns" );
STATISTIC (NumPatternImported, " Number of patterns imported from SelectionDAG" );
STATISTIC (NumPatternImportsSkipped, " Number of SelectionDAG imports skipped" );
STATISTIC (NumPatternsTested, " Number of patterns executed according to coverage information" );
STATISTIC (NumPatternEmitted, " Number of patterns emitted" );
cl::OptionCategory GlobalISelEmitterCat (" Options for -gen-global-isel" );
Expand All
@@ -62,6 +64,16 @@ static cl::opt<bool> WarnOnSkippedPatterns(
" in the GlobalISel selector" ),
cl::init(false ), cl::cat(GlobalISelEmitterCat));
static cl::opt<bool > GenerateCoverage (
" instrument-gisel-coverage" ,
cl::desc (" Generate coverage instrumentation for GlobalISel" ),
cl::init(false ), cl::cat(GlobalISelEmitterCat));
static cl::opt<std::string> UseCoverageFile (
" gisel-coverage-file" , cl::init(" " ),
cl::desc(" Specify file to retrieve coverage information from" ),
cl::cat(GlobalISelEmitterCat));
namespace {
// ===- Helper functions ---------------------------------------------------===//
Expand Down
Expand Up
@@ -569,14 +581,20 @@ class RuleMatcher {
// / A map of Symbolic Names to ComplexPattern sub-operands.
DefinedComplexPatternSubOperandMap ComplexSubOperands;
uint64_t RuleID;
static uint64_t NextRuleID;
public:
RuleMatcher (ArrayRef<SMLoc> SrcLoc)
: Matchers(), Actions(), InsnVariableIDs(), MutatableInsns(),
DefinedOperands (), NextInsnVarID(0 ), NextOutputInsnID(0 ),
NextTempRegID(0 ), SrcLoc(SrcLoc), ComplexSubOperands() {}
NextTempRegID(0 ), SrcLoc(SrcLoc), ComplexSubOperands(),
RuleID(NextRuleID++) {}
RuleMatcher (RuleMatcher &&Other) = default;
RuleMatcher &operator =(RuleMatcher &&Other) = default ;
uint64_t getRuleID () const { return RuleID; }
InstructionMatcher &addInstructionMatcher (StringRef SymbolicName);
void addRequiredFeature (Record *Feature);
const std::vector<Record *> &getRequiredFeatures () const ;
Expand Down
Expand Up
@@ -664,6 +682,8 @@ class RuleMatcher {
unsigned allocateTempRegID () { return NextTempRegID++; }
};
uint64_t RuleMatcher::NextRuleID = 0 ;
using action_iterator = RuleMatcher::action_iterator;
template <class PredicateTy > class PredicateListMatcher {
Expand Down
Expand Up
@@ -2204,6 +2224,11 @@ void RuleMatcher::emit(MatchTable &Table) {
for (const auto &MA : Actions)
MA->emitActionOpcodes (Table, *this );
if (GenerateCoverage)
Table << MatchTable::Opcode (" GIR_Coverage" ) << MatchTable::IntValue (RuleID)
<< MatchTable::LineBreak;
Table << MatchTable::Opcode (" GIR_Done" , -1 ) << MatchTable::LineBreak
<< MatchTable::Label (LabelID);
}
Expand Down
Expand Up
@@ -2309,6 +2334,9 @@ class GlobalISelEmitter {
// Map of predicates to their subtarget features.
SubtargetFeatureInfoMap SubtargetFeatures;
// Rule coverage information.
Optional<CodeGenCoverage> RuleCoverage;
void gatherNodeEquivs ();
Record *findNodeEquiv (Record *N) const ;
Expand Down
Expand Up
@@ -3227,6 +3255,20 @@ void GlobalISelEmitter::emitImmPredicates(
}
void GlobalISelEmitter::run (raw_ostream &OS) {
if (!UseCoverageFile.empty ()) {
RuleCoverage = CodeGenCoverage ();
auto RuleCoverageBufOrErr = MemoryBuffer::getFile (UseCoverageFile);
if (!RuleCoverageBufOrErr) {
PrintWarning (SMLoc (), " Missing rule coverage data" );
RuleCoverage = None;
} else {
if (!RuleCoverage->parse (*RuleCoverageBufOrErr.get (), Target.getName ())) {
PrintWarning (SMLoc (), " Ignoring invalid or missing rule coverage data" );
RuleCoverage = None;
}
}
}
// Track the GINodeEquiv definitions.
gatherNodeEquivs ();
Expand All
@@ -3252,6 +3294,13 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
continue ;
}
if (RuleCoverage) {
if (RuleCoverage->isCovered (MatcherOrErr->getRuleID ()))
++NumPatternsTested;
else
PrintWarning (Pat.getSrcRecord ()->getLoc (),
" Pattern is not covered by a test" );
}
Rules.push_back (std::move (MatcherOrErr.get ()));
}
Expand Down
Expand Up
@@ -3431,7 +3480,8 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
OS << " };\n\n " ;
OS << " bool " << Target.getName ()
<< " InstructionSelector::selectImpl(MachineInstr &I) const {\n "
<< " InstructionSelector::selectImpl(MachineInstr &I, CodeGenCoverage "
" &CoverageInfo) const {\n "
<< " MachineFunction &MF = *I.getParent()->getParent();\n "
<< " MachineRegisterInfo &MRI = MF.getRegInfo();\n "
<< " // FIXME: This should be computed on a per-function basis rather "
Expand All
@@ -3452,7 +3502,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
Table.emitDeclaration (OS);
OS << " if (executeMatchTable(*this, OutMIs, State, MatcherInfo, " ;
Table.emitUse (OS);
OS << " , TII, MRI, TRI, RBI, AvailableFeatures)) {\n "
OS << " , TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo )) {\n "
<< " return true;\n "
<< " }\n\n " ;
Expand Down