Skip to content

Commit dd0973b

Browse files
authored
[TableGen] Split GlobalISelCombinerEmitter into multiple files (#73325)
Split MatchDataInfo, CXXPredicates and the Pattern hierarchy into their own files. This should help with maintenance a bit, and make the API easier to navigate. I hope this encourages a bit more experimentation with MIR patterns, e.g. I'd like to try getting them in ISel at some point. Currently, this is pretty much only moving code around. There is no significant refactoring in there. I want to split the Combiner backend even more at some point though, e.g. by separating the TableGen parsing logic into yet another file so other backends could very easily parse patterns themselves. Note: I moved the responsibility of managing string lifetimes into the backend instead of the Pattern class. e.g. Before you'd do `P.addOperand(Name)` but now it's `P.addOperand(insertStrRef(Name))`. I verified this was done correctly by running the tests with UBSan/ASan.
1 parent eba5092 commit dd0973b

File tree

9 files changed

+1895
-1622
lines changed

9 files changed

+1895
-1622
lines changed

llvm/utils/TableGen/GlobalISel/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ set(LLVM_LINK_COMPONENTS
55

66
add_llvm_library(LLVMTableGenGlobalISel STATIC DISABLE_LLVM_LINK_LLVM_DYLIB
77
CodeExpander.cpp
8+
CXXPredicates.cpp
9+
MatchDataInfo.cpp
10+
Patterns.cpp
811

912
DEPENDS
1013
vt_gen
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===- CXXPredicates.cpp ----------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
#include "CXXPredicates.h"
13+
#include "llvm/ADT/STLExtras.h"
14+
15+
namespace llvm {
16+
namespace gi {
17+
18+
std::vector<const CXXPredicateCode *>
19+
CXXPredicateCode::getSorted(const CXXPredicateCodePool &Pool) {
20+
std::vector<const CXXPredicateCode *> Out;
21+
std::transform(Pool.begin(), Pool.end(), std::back_inserter(Out),
22+
[&](auto &Elt) { return Elt.second.get(); });
23+
sort(Out, [](const auto *A, const auto *B) { return A->ID < B->ID; });
24+
return Out;
25+
}
26+
27+
const CXXPredicateCode &CXXPredicateCode::get(CXXPredicateCodePool &Pool,
28+
std::string Code) {
29+
// Check if we already have an identical piece of code, if not, create an
30+
// entry in the pool.
31+
const auto CodeHash = hash_value(Code);
32+
if (auto It = Pool.find(CodeHash); It != Pool.end())
33+
return *It->second;
34+
35+
const auto ID = Pool.size();
36+
auto OwnedData = std::unique_ptr<CXXPredicateCode>(
37+
new CXXPredicateCode(std::move(Code), ID));
38+
const auto &DataRef = *OwnedData;
39+
Pool[CodeHash] = std::move(OwnedData);
40+
return DataRef;
41+
}
42+
43+
// TODO: Make BaseEnumName prefix configurable.
44+
CXXPredicateCode::CXXPredicateCode(std::string Code, unsigned ID)
45+
: Code(Code), ID(ID), BaseEnumName("GICombiner" + std::to_string(ID)) {}
46+
47+
CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXMatchCode;
48+
CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXApplyCode;
49+
50+
} // namespace gi
51+
} // namespace llvm
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===- CXXPredicates.h ------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file Contains utilities related to handling C++ code in MIR patterns for
10+
/// GlobalISel. C++ predicates need to be expanded, and then stored in a
11+
/// static pool until they can be emitted.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_UTILS_MIRPATTERNS_CXXPREDICATES_H
16+
#define LLVM_UTILS_MIRPATTERNS_CXXPREDICATES_H
17+
18+
#include "llvm/ADT/DenseMap.h"
19+
#include "llvm/ADT/Hashing.h"
20+
#include "llvm/ADT/StringRef.h"
21+
#include <memory>
22+
#include <string>
23+
#include <vector>
24+
25+
namespace llvm {
26+
namespace gi {
27+
28+
/// Entry into the static pool of all CXX Predicate code. This contains
29+
/// fully expanded C++ code.
30+
///
31+
/// The static pool is hidden inside the object and can be accessed through
32+
/// getAllMatchCode/getAllApplyCode
33+
///
34+
/// Note that CXXPattern trims C++ code, so the Code is already expected to be
35+
/// free of leading/trailing whitespace.
36+
class CXXPredicateCode {
37+
using CXXPredicateCodePool =
38+
DenseMap<hash_code, std::unique_ptr<CXXPredicateCode>>;
39+
static CXXPredicateCodePool AllCXXMatchCode;
40+
static CXXPredicateCodePool AllCXXApplyCode;
41+
42+
/// Sorts a `CXXPredicateCodePool` by their IDs and returns it.
43+
static std::vector<const CXXPredicateCode *>
44+
getSorted(const CXXPredicateCodePool &Pool);
45+
46+
/// Gets an instance of `CXXPredicateCode` for \p Code, or returns an already
47+
/// existing one.
48+
static const CXXPredicateCode &get(CXXPredicateCodePool &Pool,
49+
std::string Code);
50+
51+
CXXPredicateCode(std::string Code, unsigned ID);
52+
53+
public:
54+
static const CXXPredicateCode &getMatchCode(std::string Code) {
55+
return get(AllCXXMatchCode, std::move(Code));
56+
}
57+
58+
static const CXXPredicateCode &getApplyCode(std::string Code) {
59+
return get(AllCXXApplyCode, std::move(Code));
60+
}
61+
62+
static std::vector<const CXXPredicateCode *> getAllMatchCode() {
63+
return getSorted(AllCXXMatchCode);
64+
}
65+
66+
static std::vector<const CXXPredicateCode *> getAllApplyCode() {
67+
return getSorted(AllCXXApplyCode);
68+
}
69+
70+
const std::string Code;
71+
const unsigned ID;
72+
const std::string BaseEnumName;
73+
74+
bool needsUnreachable() const {
75+
return !StringRef(Code).starts_with("return");
76+
}
77+
78+
std::string getEnumNameWithPrefix(StringRef Prefix) const {
79+
return Prefix.str() + BaseEnumName;
80+
}
81+
};
82+
83+
} // namespace gi
84+
} // end namespace llvm
85+
86+
#endif // ifndef LLVM_UTILS_MIRPATTERNS_CXXPREDICATES_H

llvm/utils/TableGen/GlobalISel/CombinerUtils.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//===----------------------------------------------------------------------===//
88
//
99
/// \file Utility functions used by both Combiner backends.
10-
/// TODO: Can remove when MatchDAG-based backend is removed.
1110
//
1211
//===----------------------------------------------------------------------===//
1312

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===- MatchDataInfo.cpp ----------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
#include "MatchDataInfo.h"
13+
#include "llvm/Support/Debug.h"
14+
#include "llvm/Support/raw_ostream.h"
15+
16+
namespace llvm {
17+
namespace gi {
18+
19+
StringMap<std::vector<std::string>> AllMatchDataVars;
20+
21+
StringRef MatchDataInfo::getVariableName() const {
22+
assert(hasVariableName());
23+
return VarName;
24+
}
25+
26+
void MatchDataInfo::print(raw_ostream &OS) const {
27+
OS << "(MatchDataInfo pattern_symbol:" << PatternSymbol << " type:'" << Type
28+
<< "' var_name:" << (VarName.empty() ? "<unassigned>" : VarName) << ")";
29+
}
30+
31+
void MatchDataInfo::dump() const { print(dbgs()); }
32+
33+
void AssignMatchDataVariables(MutableArrayRef<MatchDataInfo> Infos) {
34+
static unsigned NextVarID = 0;
35+
36+
StringMap<unsigned> SeenTypes;
37+
for (auto &Info : Infos) {
38+
unsigned &NumSeen = SeenTypes[Info.getType()];
39+
auto &ExistingVars = AllMatchDataVars[Info.getType()];
40+
41+
if (NumSeen == ExistingVars.size())
42+
ExistingVars.push_back("MDInfo" + std::to_string(NextVarID++));
43+
44+
Info.setVariableName(ExistingVars[NumSeen++]);
45+
}
46+
}
47+
48+
} // namespace gi
49+
} // namespace llvm
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//===- MatchDataInfo.h ------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file Contains utilities related to handling "match data" for GlobalISel
10+
/// Combiners. Match data allows for setting some arbitrary data in the "match"
11+
/// phase and pass it down to the "apply" phase.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H
16+
#define LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H
17+
18+
#include "llvm/ADT/ArrayRef.h"
19+
#include "llvm/ADT/StringMap.h"
20+
#include "llvm/ADT/StringRef.h"
21+
#include <string>
22+
#include <vector>
23+
24+
namespace llvm {
25+
26+
class raw_ostream;
27+
28+
namespace gi {
29+
30+
/// Represents MatchData defined by the match stage and required by the apply
31+
/// stage.
32+
///
33+
/// This allows the plumbing of arbitrary data from C++ predicates between the
34+
/// stages.
35+
///
36+
/// When this class is initially created, it only has a pattern symbol and a
37+
/// type. When all of the MatchDatas declarations of a given pattern have been
38+
/// parsed, `AssignVariables` must be called to assign storage variable names to
39+
/// each MatchDataInfo.
40+
class MatchDataInfo {
41+
StringRef PatternSymbol;
42+
StringRef Type;
43+
std::string VarName;
44+
45+
public:
46+
static constexpr StringLiteral StructTypeName = "MatchInfosTy";
47+
static constexpr StringLiteral StructName = "MatchInfos";
48+
49+
MatchDataInfo(StringRef PatternSymbol, StringRef Type)
50+
: PatternSymbol(PatternSymbol), Type(Type.trim()) {}
51+
52+
StringRef getPatternSymbol() const { return PatternSymbol; };
53+
StringRef getType() const { return Type; };
54+
55+
bool hasVariableName() const { return !VarName.empty(); }
56+
void setVariableName(StringRef Name) { VarName = Name; }
57+
StringRef getVariableName() const;
58+
59+
std::string getQualifiedVariableName() const {
60+
return StructName.str() + "." + getVariableName().str();
61+
}
62+
63+
void print(raw_ostream &OS) const;
64+
void dump() const;
65+
};
66+
67+
/// Pool of type -> variables used to emit MatchData variables declarations.
68+
///
69+
/// e.g. if the map contains "int64_t" -> ["MD0", "MD1"], then two variable
70+
/// declarations must be emitted: `int64_t MD0` and `int64_t MD1`.
71+
///
72+
/// This has a static lifetime and will outlive all the `MatchDataInfo` objects
73+
/// by design. It needs a static lifetime so the backends can emit variable
74+
/// declarations after processing all the inputs.
75+
extern StringMap<std::vector<std::string>> AllMatchDataVars;
76+
77+
/// Assign variable names to all MatchDatas used by a pattern. This must be
78+
/// called after all MatchData decls have been parsed for a given processing
79+
/// unit (e.g. a combine rule)
80+
///
81+
/// Requires an array of MatchDataInfo so we can handle cases where a pattern
82+
/// uses multiple instances of the same MatchData type.
83+
///
84+
/// Writes to \ref AllMatchDataVars.
85+
void AssignMatchDataVariables(MutableArrayRef<MatchDataInfo> Infos);
86+
87+
} // namespace gi
88+
} // end namespace llvm
89+
90+
#endif // ifndef LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H

0 commit comments

Comments
 (0)