Skip to content

Commit d7c6d05

Browse files
committed
[TableGen][GlobalISel] Guarantee stable iteration order for stop-after-parse
Builds on top of 6de2735 to fix remaining issues with iteration order in the MatchTable Combiner backend. See D155789 as well. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D155821
1 parent 92a11eb commit d7c6d05

File tree

2 files changed

+57
-43
lines changed

2 files changed

+57
-43
lines changed

llvm/test/TableGen/GlobalISelCombinerMatchTableEmitter/pattern-parsing.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,16 @@ def InstTest0 : GICombineRule<
8181
// CHECK-NEXT: (MatchDataInfo pattern_symbol:r0 type:'Register' var_name:MDInfo0)
8282
// CHECK-NEXT: )
8383
// CHECK-NEXT: (MatchPats
84-
// CHECK-NEXT: __anon_pat_match_3_0:(InstructionPattern inst:ZEXT operands:[<def>x, a])
8584
// CHECK-NEXT: <root>d:(InstructionPattern inst:MOV operands:[<def>a, b])
85+
// CHECK-NEXT: __anon_pat_match_3_0:(InstructionPattern inst:ZEXT operands:[<def>x, a])
8686
// CHECK-NEXT: )
8787
// CHECK-NEXT: (ApplyPats
8888
// CHECK-NEXT: __anon_pat_apply_3_1:(CXXPattern apply code:"APPLY")
8989
// CHECK-NEXT: )
9090
// CHECK-NEXT: (OperandTable
91-
// CHECK-NEXT: [x match_pat:__anon_pat_match_3_0]
9291
// CHECK-NEXT: [a match_pat:d]
9392
// CHECK-NEXT: [b live-in]
93+
// CHECK-NEXT: [x match_pat:__anon_pat_match_3_0]
9494
// CHECK-NEXT: )
9595
// CHECK-NEXT: )
9696
let Predicates = [HasAnswerToEverything] in

llvm/utils/TableGen/GlobalISelCombinerMatchTableEmitter.cpp

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ class Pattern {
233233

234234
private:
235235
unsigned Kind;
236+
237+
// Note: if this ever changes to a StringRef (e.g. allocated in a pool or
238+
// something), CombineRuleBuilder::verify() needs to be updated as well.
239+
// It currently checks that the StringRef in the PatternMap references this.
236240
std::string Name;
237241
};
238242

@@ -454,12 +458,12 @@ struct OperandTableEntry {
454458
/// - Creation in a `parse` function
455459
/// - The unique_ptr is stored in a variable, and may be destroyed if the
456460
/// pattern is found to be semantically invalid.
457-
/// - Ownership transfer into a `PatternStringMap`
461+
/// - Ownership transfer into a `PatternMap`
458462
/// - Once a pattern is moved into either the map of Match or Apply
459463
/// patterns, it is known to be valid and it never moves back.
460464
class CombineRuleBuilder {
461465
public:
462-
using PatternStringMap = StringMap<std::unique_ptr<Pattern>>;
466+
using PatternMap = MapVector<StringRef, std::unique_ptr<Pattern>>;
463467

464468
CombineRuleBuilder(const CodeGenTarget &CGT,
465469
SubtargetFeatureInfoMap &SubtargetFeatures,
@@ -547,8 +551,8 @@ class CombineRuleBuilder {
547551

548552
/// These maps have ownership of the actual Pattern objects.
549553
/// They both map a Pattern's name to the Pattern instance.
550-
PatternStringMap MatchPats;
551-
PatternStringMap ApplyPats;
554+
PatternMap MatchPats;
555+
PatternMap ApplyPats;
552556

553557
/// Set by findRoots.
554558
Pattern *MatchRoot = nullptr;
@@ -614,20 +618,20 @@ void CombineRuleBuilder::print(raw_ostream &OS) const {
614618
OS << " )\n";
615619
}
616620

617-
const auto DumpPats = [&](StringRef Name, const PatternStringMap &Pats) {
621+
const auto DumpPats = [&](StringRef Name, const PatternMap &Pats) {
618622
OS << " (" << Name << " ";
619623
if (Pats.empty()) {
620624
OS << "<empty>)\n";
621625
return;
622626
}
623627

624628
OS << "\n";
625-
for (const auto &P : Pats) {
629+
for (const auto &[Name, Pat] : Pats) {
626630
OS << " ";
627-
if (P.getValue().get() == MatchRoot)
631+
if (Pat.get() == MatchRoot)
628632
OS << "<root>";
629-
OS << P.getKey() << ":";
630-
P.getValue()->print(OS, /*PrintName=*/false);
633+
OS << Name << ":";
634+
Pat->print(OS, /*PrintName=*/false);
631635
OS << "\n";
632636
}
633637
OS << " )\n";
@@ -658,15 +662,27 @@ void CombineRuleBuilder::print(raw_ostream &OS) const {
658662
}
659663

660664
void CombineRuleBuilder::verify() const {
661-
const auto VerifyPats = [&](const PatternStringMap &Pats) {
662-
for (const auto &Entry : Pats) {
663-
if (!Entry.getValue())
665+
const auto VerifyPats = [&](const PatternMap &Pats) {
666+
for (const auto &[Name, Pat] : Pats) {
667+
if (!Pat)
664668
PrintFatalError("null pattern in pattern map!");
665669

666-
if (Entry.getKey() != Entry.getValue()->getName()) {
667-
Entry.getValue()->dump();
668-
PrintFatalError("Pattern name mismatch! Map name: " + Entry.getKey() +
669-
", Pat name: " + Entry.getValue()->getName());
670+
if (Name != Pat->getName()) {
671+
Pat->dump();
672+
PrintFatalError("Pattern name mismatch! Map name: " + Name +
673+
", Pat name: " + Pat->getName());
674+
}
675+
676+
// As an optimization, the PatternMaps don't re-allocate the PatternName
677+
// string. They simply reference the std::string inside Pattern. Ensure
678+
// this is the case to avoid memory issues.
679+
if (Name.data() != Pat->getName().data()) {
680+
dbgs() << "Map StringRef: '" << Name << "' @ " << (void *)Name.data()
681+
<< "\n";
682+
dbgs() << "Pat String: '" << Pat->getName() << "' @ "
683+
<< (void *)Pat->getName().data() << "\n";
684+
PrintFatalError("StringRef stored in the PatternMap is not referencing "
685+
"the same string as its Pattern!");
670686
}
671687
}
672688
};
@@ -745,7 +761,7 @@ bool CombineRuleBuilder::findRoots() {
745761
// Look by pattern name, e.g.
746762
// (G_FNEG $x, $y):$root
747763
if (auto It = MatchPats.find(RootName); It != MatchPats.end()) {
748-
MatchRoot = MatchPats[RootName].get();
764+
MatchRoot = It->second.get();
749765
return true;
750766
}
751767

@@ -769,8 +785,8 @@ bool CombineRuleBuilder::findRoots() {
769785

770786
bool CombineRuleBuilder::buildOperandsTable() {
771787
// Walk each instruction pattern
772-
for (auto &P : MatchPats) {
773-
auto *IP = dyn_cast<InstructionPattern>(P.getValue().get());
788+
for (auto &[_, P] : MatchPats) {
789+
auto *IP = dyn_cast<InstructionPattern>(P.get());
774790
if (!IP)
775791
continue;
776792
for (const auto &Operand : IP->operands()) {
@@ -790,8 +806,8 @@ bool CombineRuleBuilder::buildOperandsTable() {
790806
}
791807
}
792808

793-
for (auto &P : ApplyPats) {
794-
auto *IP = dyn_cast<InstructionPattern>(P.getValue().get());
809+
for (auto &[_, P] : ApplyPats) {
810+
auto *IP = dyn_cast<InstructionPattern>(P.get());
795811
if (!IP)
796812
continue;
797813
for (const auto &Operand : IP->operands()) {
@@ -913,7 +929,7 @@ bool CombineRuleBuilder::parseMatch(DagInit &Match) {
913929
PrintWarning(RuleDef.getLoc(),
914930
"'match' C++ code does not seem to return!");
915931
}
916-
MatchPats[Name] = std::move(CXXPat);
932+
MatchPats[CXXPat->getName()] = std::move(CXXPat);
917933
continue;
918934
}
919935

@@ -940,9 +956,9 @@ bool CombineRuleBuilder::parseApply(DagInit &Apply) {
940956
}
941957

942958
const StringInit *Code = dyn_cast<StringInit>(Apply.getArg(0));
943-
const auto PatName = makeAnonPatName("apply");
944-
ApplyPats[PatName] =
945-
std::make_unique<CXXPattern>(*Code, PatName, /*IsApply*/ true);
959+
auto Pat = std::make_unique<CXXPattern>(*Code, makeAnonPatName("apply"),
960+
/*IsApply*/ true);
961+
ApplyPats[Pat->getName()] = std::move(Pat);
946962
return true;
947963
}
948964

@@ -1003,20 +1019,19 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
10031019
return false;
10041020

10051021
// Emit remaining patterns
1006-
for (auto &Entry : MatchPats) {
1007-
Pattern *CurPat = Entry.getValue().get();
1008-
if (SeenPats.contains(CurPat))
1022+
for (auto &[_, Pat] : MatchPats) {
1023+
if (SeenPats.contains(Pat.get()))
10091024
continue;
10101025

1011-
switch (CurPat->getKind()) {
1026+
switch (Pat->getKind()) {
10121027
case Pattern::K_AnyOpcode:
10131028
PrintError("wip_match_opcode can not be used with instruction patterns!");
10141029
return false;
10151030
case Pattern::K_Inst:
1016-
cast<InstructionPattern>(CurPat)->reportUnreachable(RuleDef.getLoc());
1031+
cast<InstructionPattern>(Pat.get())->reportUnreachable(RuleDef.getLoc());
10171032
return false;
10181033
case Pattern::K_CXX: {
1019-
addCXXPredicate(IM, CE, *cast<CXXPattern>(CurPat));
1034+
addCXXPredicate(IM, CE, *cast<CXXPattern>(Pat.get()));
10201035
continue;
10211036
}
10221037
default:
@@ -1043,20 +1058,20 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
10431058
IM.addPredicate<InstructionOpcodeMatcher>(CGI);
10441059

10451060
// Emit remaining patterns.
1046-
for (auto &Entry : MatchPats) {
1047-
Pattern *CurPat = Entry.getValue().get();
1048-
if (CurPat == &AOP)
1061+
for (auto &[_, Pat] : MatchPats) {
1062+
if (Pat.get() == &AOP)
10491063
continue;
10501064

1051-
switch (CurPat->getKind()) {
1065+
switch (Pat->getKind()) {
10521066
case Pattern::K_AnyOpcode:
10531067
PrintError("wip_match_opcode can only be present once!");
10541068
return false;
10551069
case Pattern::K_Inst:
1056-
cast<InstructionPattern>(CurPat)->reportUnreachable(RuleDef.getLoc());
1070+
cast<InstructionPattern>(Pat.get())->reportUnreachable(
1071+
RuleDef.getLoc());
10571072
return false;
10581073
case Pattern::K_CXX: {
1059-
addCXXPredicate(IM, CE, *cast<CXXPattern>(CurPat));
1074+
addCXXPredicate(IM, CE, *cast<CXXPattern>(Pat.get()));
10601075
break;
10611076
}
10621077
default:
@@ -1072,14 +1087,13 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
10721087
}
10731088

10741089
bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) {
1075-
for (auto &Entry : ApplyPats) {
1076-
Pattern *CurPat = Entry.getValue().get();
1077-
switch (CurPat->getKind()) {
1090+
for (auto &[_, Pat] : ApplyPats) {
1091+
switch (Pat->getKind()) {
10781092
case Pattern::K_AnyOpcode:
10791093
case Pattern::K_Inst:
10801094
llvm_unreachable("Unsupported pattern kind in output pattern!");
10811095
case Pattern::K_CXX: {
1082-
CXXPattern *CXXPat = cast<CXXPattern>(CurPat);
1096+
CXXPattern *CXXPat = cast<CXXPattern>(Pat.get());
10831097
const auto &ExpandedCode = CXXPat->expandCode(CE, RuleDef.getLoc());
10841098
M.addAction<CustomCXXAction>(
10851099
ExpandedCode.getEnumNameWithPrefix(CXXApplyPrefix));

0 commit comments

Comments
 (0)