[SelectionDAG] Add space-optimized forms of OPC_CheckComplexPat (#73310)
We record the usage of each `ComplexPat` and sort the `ComplexPat`s by usage. For the top 8 `ComplexPat`s, we will emit a `OPC_CheckComplexPatN` to save one byte. Overall this reduces the llc binary size with all in-tree targets by about 89K.
This commit is contained in:
parent
3d795bdd4d
commit
211abe38d8
@ -207,6 +207,14 @@ public:
|
||||
OPC_CheckChild2CondCode,
|
||||
OPC_CheckValueType,
|
||||
OPC_CheckComplexPat,
|
||||
OPC_CheckComplexPat0,
|
||||
OPC_CheckComplexPat1,
|
||||
OPC_CheckComplexPat2,
|
||||
OPC_CheckComplexPat3,
|
||||
OPC_CheckComplexPat4,
|
||||
OPC_CheckComplexPat5,
|
||||
OPC_CheckComplexPat6,
|
||||
OPC_CheckComplexPat7,
|
||||
OPC_CheckAndImm,
|
||||
OPC_CheckOrImm,
|
||||
OPC_CheckImmAllOnesV,
|
||||
|
||||
@ -3358,8 +3358,18 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
case OPC_CheckComplexPat: {
|
||||
unsigned CPNum = MatcherTable[MatcherIndex++];
|
||||
case OPC_CheckComplexPat:
|
||||
case OPC_CheckComplexPat0:
|
||||
case OPC_CheckComplexPat1:
|
||||
case OPC_CheckComplexPat2:
|
||||
case OPC_CheckComplexPat3:
|
||||
case OPC_CheckComplexPat4:
|
||||
case OPC_CheckComplexPat5:
|
||||
case OPC_CheckComplexPat6:
|
||||
case OPC_CheckComplexPat7: {
|
||||
unsigned CPNum = Opcode == OPC_CheckComplexPat
|
||||
? MatcherTable[MatcherIndex++]
|
||||
: Opcode - OPC_CheckComplexPat0;
|
||||
unsigned RecNo = MatcherTable[MatcherIndex++];
|
||||
assert(RecNo < RecordedNodes.size() && "Invalid CheckComplexPat");
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ def CP32 : ComplexPattern<i32, 0, "SelectCP32">;
|
||||
def INSTR : Instruction {
|
||||
// CHECK-LABEL: OPC_CheckOpcode, TARGET_VAL(ISD::STORE)
|
||||
// CHECK: OPC_CheckTypeI32
|
||||
// CHECK: OPC_CheckComplexPat, /*CP*/0, /*#*/1, // SelectCP32:$
|
||||
// CHECK: OPC_CheckComplexPat0, /*#*/1, // SelectCP32:$
|
||||
// CHECK: Src: (st (add:{ *:[i32] } (CP32:{ *:[i32] }), (CP32:{ *:[i32] })), i64:{ *:[i64] }:$addr)
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins GPR64:$addr);
|
||||
|
||||
@ -63,7 +63,6 @@ class MatcherTableEmitter {
|
||||
StringMap<unsigned> PatternPredicateMap;
|
||||
std::vector<std::string> PatternPredicates;
|
||||
|
||||
DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
|
||||
std::vector<const ComplexPattern*> ComplexPatterns;
|
||||
|
||||
|
||||
@ -84,8 +83,38 @@ class MatcherTableEmitter {
|
||||
}
|
||||
|
||||
public:
|
||||
MatcherTableEmitter(const CodeGenDAGPatterns &cgp)
|
||||
: CGP(cgp), OpcodeCounts(Matcher::HighestKind + 1, 0) {}
|
||||
MatcherTableEmitter(const Matcher *TheMatcher, const CodeGenDAGPatterns &cgp)
|
||||
: CGP(cgp), OpcodeCounts(Matcher::HighestKind + 1, 0) {
|
||||
// Record the usage of ComplexPattern.
|
||||
DenseMap<const ComplexPattern *, unsigned> ComplexPatternUsage;
|
||||
|
||||
// Iterate the whole MatcherTable once and do some statistics.
|
||||
std::function<void(const Matcher *)> Statistic = [&](const Matcher *N) {
|
||||
while (N) {
|
||||
if (auto *SM = dyn_cast<ScopeMatcher>(N))
|
||||
for (unsigned I = 0; I < SM->getNumChildren(); I++)
|
||||
Statistic(SM->getChild(I));
|
||||
else if (auto *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
|
||||
for (unsigned I = 0; I < SOM->getNumCases(); I++)
|
||||
Statistic(SOM->getCaseMatcher(I));
|
||||
else if (auto *STM = dyn_cast<SwitchTypeMatcher>(N))
|
||||
for (unsigned I = 0; I < STM->getNumCases(); I++)
|
||||
Statistic(STM->getCaseMatcher(I));
|
||||
else if (auto *CPM = dyn_cast<CheckComplexPatMatcher>(N))
|
||||
++ComplexPatternUsage[&CPM->getPattern()];
|
||||
N = N->getNext();
|
||||
}
|
||||
};
|
||||
Statistic(TheMatcher);
|
||||
|
||||
// Sort ComplexPatterns by usage.
|
||||
std::vector<std::pair<const ComplexPattern *, unsigned>> ComplexPatternList(
|
||||
ComplexPatternUsage.begin(), ComplexPatternUsage.end());
|
||||
sort(ComplexPatternList,
|
||||
[](const auto &A, const auto &B) { return A.second > B.second; });
|
||||
for (const auto &ComplexPattern : ComplexPatternList)
|
||||
ComplexPatterns.push_back(ComplexPattern.first);
|
||||
}
|
||||
|
||||
unsigned EmitMatcherList(const Matcher *N, const unsigned Indent,
|
||||
unsigned StartIdx, raw_ostream &OS);
|
||||
@ -146,12 +175,7 @@ private:
|
||||
return Entry-1;
|
||||
}
|
||||
unsigned getComplexPat(const ComplexPattern &P) {
|
||||
unsigned &Entry = ComplexPatternMap[&P];
|
||||
if (Entry == 0) {
|
||||
ComplexPatterns.push_back(&P);
|
||||
Entry = ComplexPatterns.size();
|
||||
}
|
||||
return Entry-1;
|
||||
return llvm::find(ComplexPatterns, &P) - ComplexPatterns.begin();
|
||||
}
|
||||
|
||||
unsigned getNodeXFormID(Record *Rec) {
|
||||
@ -652,8 +676,13 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
|
||||
case Matcher::CheckComplexPat: {
|
||||
const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);
|
||||
const ComplexPattern &Pattern = CCPM->getPattern();
|
||||
OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
|
||||
<< CCPM->getMatchNumber() << ',';
|
||||
unsigned PatternNo = getComplexPat(Pattern);
|
||||
if (PatternNo < 8)
|
||||
OS << "OPC_CheckComplexPat" << PatternNo << ", /*#*/"
|
||||
<< CCPM->getMatchNumber() << ',';
|
||||
else
|
||||
OS << "OPC_CheckComplexPat, /*CP*/" << PatternNo << ", /*#*/"
|
||||
<< CCPM->getMatchNumber() << ',';
|
||||
|
||||
if (!OmitComments) {
|
||||
OS << " // " << Pattern.getSelectFunc();
|
||||
@ -665,7 +694,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
|
||||
OS << " + chain result";
|
||||
}
|
||||
OS << '\n';
|
||||
return 3;
|
||||
return PatternNo < 8 ? 2 : 3;
|
||||
}
|
||||
|
||||
case Matcher::CheckAndImm: {
|
||||
@ -1267,7 +1296,7 @@ void llvm::EmitMatcherTable(Matcher *TheMatcher,
|
||||
OS << "#endif\n\n";
|
||||
|
||||
BeginEmitFunction(OS, "void", "SelectCode(SDNode *N)", false/*AddOverride*/);
|
||||
MatcherTableEmitter MatcherEmitter(CGP);
|
||||
MatcherTableEmitter MatcherEmitter(TheMatcher, CGP);
|
||||
|
||||
// First we size all the children of the three kinds of matchers that have
|
||||
// them. This is done by sharing the code in EmitMatcher(). but we don't
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user