[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:
Wang Pengcheng 2024-01-11 15:28:12 +08:00 committed by GitHub
parent 3d795bdd4d
commit 211abe38d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 16 deletions

View File

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

View File

@ -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");

View File

@ -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);

View File

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