mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[Tablegen] Instrumenting table gen DAGGenISelDAG
To help assist in debugging ISEL or to prioritize GlobalISel backend work, this patch adds two more tables to <Target>GenISelDAGISel.inc - one which contains the patterns that are used during selection and the other containing include source location of the patterns Enabled through CMake varialbe LLVM_ENABLE_DAGISEL_COV llvm-svn: 295081
This commit is contained in:
parent
72bbc3337e
commit
b5cce55dd5
@ -174,6 +174,8 @@ if(LLVM_BUILD_GLOBAL_ISEL)
|
||||
add_definitions(-DLLVM_BUILD_GLOBAL_ISEL)
|
||||
endif()
|
||||
|
||||
option(LLVM_ENABLE_DAGISEL_COV "Debug: Prints tablegen patterns that were used for selecting" OFF)
|
||||
|
||||
# Add path for custom modules
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
|
@ -23,6 +23,13 @@ function(tablegen project ofn)
|
||||
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS})
|
||||
endif()
|
||||
if (LLVM_ENABLE_DAGISEL_COV)
|
||||
list(FIND ARGN "-gen-dag-isel" idx)
|
||||
if( NOT idx EQUAL -1 )
|
||||
list(APPEND LLVM_TABLEGEN_FLAGS "-instrument-coverage")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
|
||||
# Generate tablegen output in a temporary file.
|
||||
COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
|
@ -152,7 +152,9 @@ public:
|
||||
OPC_MorphNodeTo,
|
||||
// Space-optimized forms that implicitly encode number of result VTs.
|
||||
OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2,
|
||||
OPC_CompleteMatch
|
||||
OPC_CompleteMatch,
|
||||
// Contains offset in table for pattern being selected
|
||||
OPC_Coverage
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -214,6 +216,15 @@ protected:
|
||||
void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
|
||||
const SDLoc &DL);
|
||||
|
||||
/// getPatternForIndex - Patterns selected by tablegen during ISEL
|
||||
virtual StringRef getPatternForIndex(unsigned index) {
|
||||
llvm_unreachable("Tblgen should generate the implementation of this!");
|
||||
}
|
||||
|
||||
/// getIncludePathForIndex - get the td source location of pattern instantiation
|
||||
virtual StringRef getIncludePathForIndex(unsigned index) {
|
||||
llvm_unreachable("Tblgen should generate the implementation of this!");
|
||||
}
|
||||
public:
|
||||
// Calls to these predicates are generated by tblgen.
|
||||
bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS,
|
||||
|
@ -3505,6 +3505,15 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
|
||||
RecordedNodes.push_back(std::pair<SDValue,SDNode*>(Res, nullptr));
|
||||
continue;
|
||||
}
|
||||
case OPC_Coverage: {
|
||||
// This is emitted right before MorphNode/EmitNode.
|
||||
// So it should be safe to assume that this node has been selected
|
||||
unsigned index = MatcherTable[MatcherIndex++];
|
||||
index |= (MatcherTable[MatcherIndex++] << 8);
|
||||
dbgs() << "COVERED: " << getPatternForIndex(index) << "\n";
|
||||
dbgs() << "INCLUDED: " << getIncludePathForIndex(index) << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
case OPC_EmitNode: case OPC_MorphNodeTo:
|
||||
case OPC_EmitNode0: case OPC_EmitNode1: case OPC_EmitNode2:
|
||||
|
@ -11,14 +11,18 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DAGISelMatcher.h"
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
#include "DAGISelMatcher.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
using namespace llvm;
|
||||
|
||||
@ -31,6 +35,11 @@ static cl::opt<bool>
|
||||
OmitComments("omit-comments", cl::desc("Do not generate comments"),
|
||||
cl::init(false));
|
||||
|
||||
static cl::opt<bool> InstrumentCoverage(
|
||||
"instrument-coverage",
|
||||
cl::desc("Generates tables to help identify patterns matched"),
|
||||
cl::init(false));
|
||||
|
||||
namespace {
|
||||
class MatcherTableEmitter {
|
||||
const CodeGenDAGPatterns &CGP;
|
||||
@ -52,6 +61,19 @@ class MatcherTableEmitter {
|
||||
DenseMap<Record*, unsigned> NodeXFormMap;
|
||||
std::vector<Record*> NodeXForms;
|
||||
|
||||
std::vector<std::string> VecIncludeStrings;
|
||||
MapVector<std::string, unsigned, StringMap<unsigned> > VecPatterns;
|
||||
|
||||
unsigned getPatternIdxFromTable(std::string &&P, std::string &&include_loc) {
|
||||
const auto It = VecPatterns.find(P);
|
||||
if (It == VecPatterns.end()) {
|
||||
VecPatterns.insert(make_pair(std::move(P), VecPatterns.size()));
|
||||
VecIncludeStrings.push_back(std::move(include_loc));
|
||||
return VecIncludeStrings.size() - 1;
|
||||
}
|
||||
return It->second;
|
||||
}
|
||||
|
||||
public:
|
||||
MatcherTableEmitter(const CodeGenDAGPatterns &cgp)
|
||||
: CGP(cgp) {}
|
||||
@ -62,6 +84,9 @@ public:
|
||||
void EmitPredicateFunctions(formatted_raw_ostream &OS);
|
||||
|
||||
void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
|
||||
|
||||
void EmitPatternMatchTable(raw_ostream &OS);
|
||||
|
||||
private:
|
||||
unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
|
||||
formatted_raw_ostream &OS);
|
||||
@ -117,6 +142,14 @@ private:
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
static std::string GetPatFromTreePatternNode(const TreePatternNode *N) {
|
||||
std::string str;
|
||||
raw_string_ostream Stream(str);
|
||||
Stream << *N;
|
||||
Stream.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
static unsigned GetVBRSize(unsigned Val) {
|
||||
if (Val <= 127) return 1;
|
||||
|
||||
@ -150,6 +183,56 @@ static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
|
||||
return NumBytes+1;
|
||||
}
|
||||
|
||||
// This is expensive and slow.
|
||||
static std::string getIncludePath(const Record *R) {
|
||||
std::string str;
|
||||
raw_string_ostream Stream(str);
|
||||
auto Locs = R->getLoc();
|
||||
SMLoc L;
|
||||
if (Locs.size() > 1) {
|
||||
// Get where the pattern prototype was instantiated
|
||||
L = Locs[1];
|
||||
} else if (Locs.size() == 1) {
|
||||
L = Locs[0];
|
||||
}
|
||||
unsigned CurBuf = SrcMgr.FindBufferContainingLoc(L);
|
||||
assert(CurBuf && "Invalid or unspecified location!");
|
||||
|
||||
Stream << SrcMgr.getBufferInfo(CurBuf).Buffer->getBufferIdentifier() << ":"
|
||||
<< SrcMgr.FindLineNumber(L, CurBuf);
|
||||
Stream.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
|
||||
|
||||
assert(isUInt<16>(VecPatterns.size()) &&
|
||||
"Using only 16 bits to encode offset into Pattern Table");
|
||||
assert(VecPatterns.size() == VecIncludeStrings.size() &&
|
||||
"The sizes of Pattern and include vectors should be the same");
|
||||
OS << "StringRef getPatternForIndex(unsigned Index) override {\n";
|
||||
OS << "static const char * PATTERN_MATCH_TABLE[] = {\n";
|
||||
|
||||
for (const auto &It : VecPatterns) {
|
||||
OS << "\"" << It.first << "\",\n";
|
||||
}
|
||||
|
||||
OS << "\n};";
|
||||
OS << "\nreturn StringRef(PATTERN_MATCH_TABLE[Index]);";
|
||||
OS << "\n}";
|
||||
|
||||
OS << "\nStringRef getIncludePathForIndex(unsigned Index) override {\n";
|
||||
OS << "static const char * INCLUDE_PATH_TABLE[] = {\n";
|
||||
|
||||
for (const auto &It : VecIncludeStrings) {
|
||||
OS << "\"" << It << "\",\n";
|
||||
}
|
||||
|
||||
OS << "\n};";
|
||||
OS << "\nreturn StringRef(INCLUDE_PATH_TABLE[Index]);";
|
||||
OS << "\n}";
|
||||
}
|
||||
|
||||
/// EmitMatcher - Emit bytes for the specified matcher and return
|
||||
/// the number of bytes emitted.
|
||||
unsigned MatcherTableEmitter::
|
||||
@ -537,6 +620,23 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
|
||||
|
||||
case Matcher::EmitNode:
|
||||
case Matcher::MorphNodeTo: {
|
||||
auto NumCoveredBytes = 0;
|
||||
if (InstrumentCoverage) {
|
||||
if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
|
||||
NumCoveredBytes = 3;
|
||||
OS << "OPC_Coverage, ";
|
||||
std::string src =
|
||||
GetPatFromTreePatternNode(SNT->getPattern().getSrcPattern());
|
||||
std::string dst =
|
||||
GetPatFromTreePatternNode(SNT->getPattern().getDstPattern());
|
||||
Record *PatRecord = SNT->getPattern().getSrcRecord();
|
||||
std::string include_src = getIncludePath(PatRecord);
|
||||
unsigned Offset =
|
||||
getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));
|
||||
OS << "TARGET_VAL(" << Offset << "),\n";
|
||||
OS.PadToColumn(Indent * 2);
|
||||
}
|
||||
}
|
||||
const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
|
||||
OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
|
||||
bool CompressVTs = EN->getNumVTs() < 3;
|
||||
@ -593,10 +693,26 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
|
||||
} else
|
||||
OS << '\n';
|
||||
|
||||
return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes;
|
||||
return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes +
|
||||
NumCoveredBytes;
|
||||
}
|
||||
case Matcher::CompleteMatch: {
|
||||
const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
|
||||
auto NumCoveredBytes = 0;
|
||||
if (InstrumentCoverage) {
|
||||
NumCoveredBytes = 3;
|
||||
OS << "OPC_Coverage, ";
|
||||
std::string src =
|
||||
GetPatFromTreePatternNode(CM->getPattern().getSrcPattern());
|
||||
std::string dst =
|
||||
GetPatFromTreePatternNode(CM->getPattern().getDstPattern());
|
||||
Record *PatRecord = CM->getPattern().getSrcRecord();
|
||||
std::string include_src = getIncludePath(PatRecord);
|
||||
unsigned Offset =
|
||||
getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));
|
||||
OS << "TARGET_VAL(" << Offset << "),\n";
|
||||
OS.PadToColumn(Indent * 2);
|
||||
}
|
||||
OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
|
||||
unsigned NumResultBytes = 0;
|
||||
for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
|
||||
@ -610,7 +726,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
|
||||
<< *CM->getPattern().getDstPattern();
|
||||
}
|
||||
OS << '\n';
|
||||
return 2 + NumResultBytes;
|
||||
return 2 + NumResultBytes + NumCoveredBytes;
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Unreachable");
|
||||
@ -686,8 +802,13 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
|
||||
++NumOps; // Get the chained node too.
|
||||
|
||||
OS << " case " << i << ":\n";
|
||||
if (InstrumentCoverage)
|
||||
OS << " {\n";
|
||||
OS << " Result.resize(NextRes+" << NumOps << ");\n";
|
||||
OS << " return " << P.getSelectFunc();
|
||||
if (InstrumentCoverage)
|
||||
OS << " bool Succeeded = " << P.getSelectFunc();
|
||||
else
|
||||
OS << " return " << P.getSelectFunc();
|
||||
|
||||
OS << "(";
|
||||
// If the complex pattern wants the root of the match, pass it in as the
|
||||
@ -704,6 +825,13 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
|
||||
for (unsigned i = 0; i != NumOps; ++i)
|
||||
OS << ", Result[NextRes+" << i << "].first";
|
||||
OS << ");\n";
|
||||
if (InstrumentCoverage) {
|
||||
OS << " if (Succeeded)\n";
|
||||
OS << " dbgs() << \"\\nCOMPLEX_PATTERN: " << P.getSelectFunc()
|
||||
<< "\\n\" ;\n";
|
||||
OS << " return Succeeded;\n";
|
||||
OS << " }\n";
|
||||
}
|
||||
}
|
||||
OS << " }\n";
|
||||
OS << "}\n\n";
|
||||
@ -847,4 +975,7 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher,
|
||||
|
||||
// Next up, emit the function for node and pattern predicates:
|
||||
MatcherEmitter.EmitPredicateFunctions(OS);
|
||||
|
||||
if (InstrumentCoverage)
|
||||
MatcherEmitter.EmitPatternMatchTable(OS);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user