Skip to content

Commit e8c1533

Browse files
committed
[SelectionDAG] Add space-optimized forms of OPC_CheckPredicate
We record the usage of each `Predicate` and sort them by usage. For the top 8 `Predicate`s, we will emit a `PC_CheckPredicateN` to save one byte. Overall this reduces the llc binary size with all in-tree targets by about 61K. This PR is stacked on #73310.
1 parent 5c8d123 commit e8c1533

File tree

5 files changed

+94
-45
lines changed

5 files changed

+94
-45
lines changed

llvm/include/llvm/CodeGen/SelectionDAGISel.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ class SelectionDAGISel : public MachineFunctionPass {
169169
OPC_CheckPatternPredicate7,
170170
OPC_CheckPatternPredicateTwoByte,
171171
OPC_CheckPredicate,
172+
OPC_CheckPredicate0,
173+
OPC_CheckPredicate1,
174+
OPC_CheckPredicate2,
175+
OPC_CheckPredicate3,
176+
OPC_CheckPredicate4,
177+
OPC_CheckPredicate5,
178+
OPC_CheckPredicate6,
179+
OPC_CheckPredicate7,
172180
OPC_CheckPredicateWithOperands,
173181
OPC_CheckOpcode,
174182
OPC_SwitchOpcode,

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,9 +2712,13 @@ CheckPatternPredicate(unsigned Opcode, const unsigned char *MatcherTable,
27122712

27132713
/// CheckNodePredicate - Implements OP_CheckNodePredicate.
27142714
LLVM_ATTRIBUTE_ALWAYS_INLINE static bool
2715-
CheckNodePredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex,
2716-
const SelectionDAGISel &SDISel, SDNode *N) {
2717-
return SDISel.CheckNodePredicate(N, MatcherTable[MatcherIndex++]);
2715+
CheckNodePredicate(unsigned Opcode, const unsigned char *MatcherTable,
2716+
unsigned &MatcherIndex, const SelectionDAGISel &SDISel,
2717+
SDNode *N) {
2718+
unsigned PredNo = Opcode == SelectionDAGISel::OPC_CheckPredicate
2719+
? MatcherTable[MatcherIndex++]
2720+
: Opcode - SelectionDAGISel::OPC_CheckPredicate0;
2721+
return SDISel.CheckNodePredicate(N, PredNo);
27182722
}
27192723

27202724
LLVM_ATTRIBUTE_ALWAYS_INLINE static bool
@@ -2868,7 +2872,15 @@ static unsigned IsPredicateKnownToFail(const unsigned char *Table,
28682872
Result = !::CheckPatternPredicate(Opcode, Table, Index, SDISel);
28692873
return Index;
28702874
case SelectionDAGISel::OPC_CheckPredicate:
2871-
Result = !::CheckNodePredicate(Table, Index, SDISel, N.getNode());
2875+
case SelectionDAGISel::OPC_CheckPredicate0:
2876+
case SelectionDAGISel::OPC_CheckPredicate1:
2877+
case SelectionDAGISel::OPC_CheckPredicate2:
2878+
case SelectionDAGISel::OPC_CheckPredicate3:
2879+
case SelectionDAGISel::OPC_CheckPredicate4:
2880+
case SelectionDAGISel::OPC_CheckPredicate5:
2881+
case SelectionDAGISel::OPC_CheckPredicate6:
2882+
case SelectionDAGISel::OPC_CheckPredicate7:
2883+
Result = !::CheckNodePredicate(Opcode, Table, Index, SDISel, N.getNode());
28722884
return Index;
28732885
case SelectionDAGISel::OPC_CheckOpcode:
28742886
Result = !::CheckOpcode(Table, Index, N.getNode());
@@ -3359,8 +3371,16 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
33593371
if (!::CheckPatternPredicate(Opcode, MatcherTable, MatcherIndex, *this))
33603372
break;
33613373
continue;
3374+
case SelectionDAGISel::OPC_CheckPredicate0:
3375+
case SelectionDAGISel::OPC_CheckPredicate1:
3376+
case SelectionDAGISel::OPC_CheckPredicate2:
3377+
case SelectionDAGISel::OPC_CheckPredicate3:
3378+
case SelectionDAGISel::OPC_CheckPredicate4:
3379+
case SelectionDAGISel::OPC_CheckPredicate5:
3380+
case SelectionDAGISel::OPC_CheckPredicate6:
3381+
case SelectionDAGISel::OPC_CheckPredicate7:
33623382
case OPC_CheckPredicate:
3363-
if (!::CheckNodePredicate(MatcherTable, MatcherIndex, *this,
3383+
if (!::CheckNodePredicate(Opcode, MatcherTable, MatcherIndex, *this,
33643384
N.getNode()))
33653385
break;
33663386
continue;

llvm/test/TableGen/address-space-patfrags.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def inst_d : Instruction {
4646
let InOperandList = (ins GPR32:$src0, GPR32:$src1);
4747
}
4848

49-
// SDAG: case 2: {
49+
// SDAG: case 1: {
5050
// SDAG-NEXT: // Predicate_pat_frag_b
5151
// SDAG-NEXT: // Predicate_truncstorei16_addrspace
5252
// SDAG-NEXT: SDNode *N = Node;
@@ -69,7 +69,7 @@ def : Pat <
6969
>;
7070

7171

72-
// SDAG: case 3: {
72+
// SDAG: case 6: {
7373
// SDAG: // Predicate_pat_frag_a
7474
// SDAG-NEXT: SDNode *N = Node;
7575
// SDAG-NEXT: (void)N;

llvm/test/TableGen/predicate-patfags.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ def TGTmul24_oneuse : PatFrag<
3939
}
4040

4141
// SDAG: OPC_CheckOpcode, TARGET_VAL(ISD::INTRINSIC_W_CHAIN),
42-
// SDAG: OPC_CheckPredicate, 0, // Predicate_TGTmul24_oneuse
42+
// SDAG: OPC_CheckPredicate0, // Predicate_TGTmul24_oneuse
4343

4444
// SDAG: OPC_CheckOpcode, TARGET_VAL(TargetISD::MUL24),
45-
// SDAG: OPC_CheckPredicate, 0, // Predicate_TGTmul24_oneuse
45+
// SDAG: OPC_CheckPredicate0, // Predicate_TGTmul24_oneuse
4646

4747
// GISEL: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS),
4848
// GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, GIMT_Encode2(Intrinsic::tgt_mul24),

llvm/utils/TableGen/DAGISelMatcherEmitter.cpp

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ class MatcherTableEmitter {
5252

5353
SmallVector<unsigned, Matcher::HighestKind+1> OpcodeCounts;
5454

55-
DenseMap<TreePattern *, unsigned> NodePredicateMap;
56-
std::vector<TreePredicateFn> NodePredicates;
57-
std::vector<TreePredicateFn> NodePredicatesWithOperands;
55+
std::vector<TreePattern *> NodePredicates;
56+
std::vector<TreePattern *> NodePredicatesWithOperands;
5857

5958
// We de-duplicate the predicates by code string, and use this map to track
6059
// all the patterns with "identical" predicates.
@@ -88,6 +87,8 @@ class MatcherTableEmitter {
8887
DenseMap<const ComplexPattern *, unsigned> ComplexPatternUsage;
8988
// Record the usage of PatternPredicate.
9089
std::map<StringRef, unsigned> PatternPredicateUsage;
90+
// Record the usage of Predicate.
91+
DenseMap<TreePattern *, unsigned> PredicateUsage;
9192

9293
// Iterate the whole MatcherTable once and do some statistics.
9394
std::function<void(const Matcher *)> Statistic = [&](const Matcher *N) {
@@ -105,6 +106,8 @@ class MatcherTableEmitter {
105106
++ComplexPatternUsage[&CPM->getPattern()];
106107
else if (auto *CPPM = dyn_cast<CheckPatternPredicateMatcher>(N))
107108
++PatternPredicateUsage[CPPM->getPredicate()];
109+
else if (auto *PM = dyn_cast<CheckPredicateMatcher>(N))
110+
++PredicateUsage[PM->getPredicate().getOrigPatFragRecord()];
108111
N = N->getNext();
109112
}
110113
};
@@ -125,6 +128,39 @@ class MatcherTableEmitter {
125128
[](const auto &A, const auto &B) { return A.second > B.second; });
126129
for (const auto &PatternPredicate : PatternPredicateList)
127130
PatternPredicates.push_back(PatternPredicate.first);
131+
132+
// Sort Predicates by usage.
133+
// Merge predicates with same code.
134+
for (const auto &Usage : PredicateUsage) {
135+
TreePattern *TP = Usage.first;
136+
TreePredicateFn Pred(TP);
137+
NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()].push_back(TP);
138+
}
139+
140+
std::vector<std::pair<TreePattern *, unsigned>> PredicateList;
141+
// Sum the usage.
142+
for (auto &Predicate : NodePredicatesByCodeToRun) {
143+
TinyPtrVector<TreePattern *> &TPs = Predicate.second;
144+
sort(TPs, [](const auto *A, const auto *B) {
145+
return A->getRecord()->getName() < B->getRecord()->getName();
146+
});
147+
unsigned Uses = 0;
148+
for (TreePattern *TP : TPs)
149+
Uses += PredicateUsage.at(TP);
150+
151+
// We only add the first predicate here since they are with the same code.
152+
PredicateList.push_back({TPs[0], Uses});
153+
}
154+
155+
sort(PredicateList,
156+
[](const auto &A, const auto &B) { return A.second > B.second; });
157+
for (const auto &Predicate : PredicateList) {
158+
TreePattern *TP = Predicate.first;
159+
if (TreePredicateFn(TP).usesOperands())
160+
NodePredicatesWithOperands.push_back(TP);
161+
else
162+
NodePredicates.push_back(TP);
163+
}
128164
}
129165

130166
unsigned EmitMatcherList(const Matcher *N, const unsigned Indent,
@@ -139,7 +175,7 @@ class MatcherTableEmitter {
139175
void EmitPatternMatchTable(raw_ostream &OS);
140176

141177
private:
142-
void EmitNodePredicatesFunction(const std::vector<TreePredicateFn> &Preds,
178+
void EmitNodePredicatesFunction(const std::vector<TreePattern *> &Preds,
143179
StringRef Decl, raw_ostream &OS);
144180

145181
unsigned SizeMatcher(Matcher *N, raw_ostream &OS);
@@ -148,33 +184,13 @@ class MatcherTableEmitter {
148184
raw_ostream &OS);
149185

150186
unsigned getNodePredicate(TreePredicateFn Pred) {
151-
TreePattern *TP = Pred.getOrigPatFragRecord();
152-
unsigned &Entry = NodePredicateMap[TP];
153-
if (Entry == 0) {
154-
TinyPtrVector<TreePattern *> &SameCodePreds =
155-
NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()];
156-
if (SameCodePreds.empty()) {
157-
// We've never seen a predicate with the same code: allocate an entry.
158-
if (Pred.usesOperands()) {
159-
NodePredicatesWithOperands.push_back(Pred);
160-
Entry = NodePredicatesWithOperands.size();
161-
} else {
162-
NodePredicates.push_back(Pred);
163-
Entry = NodePredicates.size();
164-
}
165-
} else {
166-
// We did see an identical predicate: re-use it.
167-
Entry = NodePredicateMap[SameCodePreds.front()];
168-
assert(Entry != 0);
169-
assert(TreePredicateFn(SameCodePreds.front()).usesOperands() ==
170-
Pred.usesOperands() &&
171-
"PatFrags with some code must have same usesOperands setting");
172-
}
173-
// In both cases, we've never seen this particular predicate before, so
174-
// mark it in the list of predicates sharing the same code.
175-
SameCodePreds.push_back(TP);
176-
}
177-
return Entry-1;
187+
// We use the first predicate.
188+
TreePattern *PredPat =
189+
NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()][0];
190+
return Pred.usesOperands()
191+
? llvm::find(NodePredicatesWithOperands, PredPat) -
192+
NodePredicatesWithOperands.begin()
193+
: llvm::find(NodePredicates, PredPat) - NodePredicates.begin();
178194
}
179195

180196
unsigned getPatternPredicate(StringRef PredName) {
@@ -529,6 +545,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
529545
case Matcher::CheckPredicate: {
530546
TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
531547
unsigned OperandBytes = 0;
548+
unsigned PredNo = getNodePredicate(Pred);
532549

533550
if (Pred.usesOperands()) {
534551
unsigned NumOps = cast<CheckPredicateMatcher>(N)->getNumOperands();
@@ -537,10 +554,15 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
537554
OS << cast<CheckPredicateMatcher>(N)->getOperandNo(i) << ", ";
538555
OperandBytes = 1 + NumOps;
539556
} else {
540-
OS << "OPC_CheckPredicate, ";
557+
if (PredNo < 8) {
558+
OperandBytes = -1;
559+
OS << "OPC_CheckPredicate" << PredNo << ", ";
560+
} else
561+
OS << "OPC_CheckPredicate, ";
541562
}
542563

543-
OS << getNodePredicate(Pred) << ',';
564+
if (PredNo >= 8 || Pred.usesOperands())
565+
OS << PredNo << ',';
544566
if (!OmitComments)
545567
OS << " // " << Pred.getFnName();
546568
OS << '\n';
@@ -1029,8 +1051,7 @@ EmitMatcherList(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
10291051
}
10301052

10311053
void MatcherTableEmitter::EmitNodePredicatesFunction(
1032-
const std::vector<TreePredicateFn> &Preds, StringRef Decl,
1033-
raw_ostream &OS) {
1054+
const std::vector<TreePattern *> &Preds, StringRef Decl, raw_ostream &OS) {
10341055
if (Preds.empty())
10351056
return;
10361057

@@ -1040,7 +1061,7 @@ void MatcherTableEmitter::EmitNodePredicatesFunction(
10401061
OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
10411062
for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
10421063
// Emit the predicate code corresponding to this pattern.
1043-
const TreePredicateFn PredFn = Preds[i];
1064+
TreePredicateFn PredFn(Preds[i]);
10441065
assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
10451066
std::string PredFnCodeStr = PredFn.getCodeToRunOnSDNode();
10461067

0 commit comments

Comments
 (0)