14 #include "llvm/ADT/SmallPtrSet.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/Support/FormatVariadic.h"
18 #include "llvm/TableGen/Error.h"
19 #include "llvm/TableGen/Record.h"
22 using namespace tblgen;
25 using llvm::SpecificBumpPtrAllocator;
28 Pred::Pred(
const Record *record) : def(record) {
29 assert(def->isSubClassOf(
"Pred") &&
30 "must be a subclass of TableGen 'Pred' class");
34 Pred::Pred(
const Init *init) {
35 if (
const auto *defInit = dyn_cast_or_null<llvm::DefInit>(init))
36 def = defInit->getDef();
41 if (
def->isSubClassOf(
"CombinedPred"))
42 return static_cast<const CombinedPred *
>(
this)->getConditionImpl();
43 if (
def->isSubClassOf(
"CPred"))
45 llvm_unreachable(
"Pred::getCondition must be overridden in subclasses");
49 return def &&
def->isSubClassOf(
"CombinedPred");
55 assert(
def->isSubClassOf(
"CPred") &&
56 "must be a subclass of Tablegen 'CPred' class");
60 assert((!
def ||
def->isSubClassOf(
"CPred")) &&
61 "must be a subclass of Tablegen 'CPred' class");
66 assert(!
isNull() &&
"null predicate does not have a condition");
67 return std::string(
def->getValueAsString(
"predExpr"));
71 assert(
def->isSubClassOf(
"CombinedPred") &&
72 "must be a subclass of Tablegen 'CombinedPred' class");
76 assert((!
def ||
def->isSubClassOf(
"CombinedPred")) &&
77 "must be a subclass of Tablegen 'CombinedPred' class");
81 assert(
def->getValue(
"kind") &&
"CombinedPred must have a value 'kind'");
82 return def->getValueAsDef(
"kind");
86 assert(
def->getValue(
"children") &&
87 "CombinedPred must have a value 'children'");
88 return def->getValueAsListOfDefs(
"children");
93 enum class PredCombinerKind {
107 PredCombinerKind kind;
108 const Pred *predicate;
122 return PredCombinerKind::Leaf;
124 const auto &combinedPred =
static_cast<const CombinedPred &
>(pred);
126 combinedPred.getCombinerDef()->getName())
127 .Case(
"PredCombinerAnd", PredCombinerKind::And)
128 .Case(
"PredCombinerOr", PredCombinerKind::Or)
129 .Case(
"PredCombinerNot", PredCombinerKind::Not)
130 .Case(
"PredCombinerSubstLeaves", PredCombinerKind::SubstLeaves)
131 .Case(
"PredCombinerConcat", PredCombinerKind::Concat);
136 using Subst = std::pair<StringRef, StringRef>;
143 for (
const auto &subst : llvm::reverse(substitutions)) {
144 auto pos = str.find(std::string(subst.first));
145 while (pos != std::string::npos) {
146 str.replace(pos, subst.first.size(), std::string(subst.second));
149 pos += subst.second.size();
151 pos = str.find(std::string(subst.first), pos);
162 SpecificBumpPtrAllocator<PredNode> &allocator,
164 auto *rootNode = allocator.Allocate();
165 new (rootNode) PredNode;
167 rootNode->predicate = &root;
176 auto allSubstitutions = llvm::to_vector<4>(substitutions);
177 if (rootNode->kind == PredCombinerKind::SubstLeaves) {
179 allSubstitutions.push_back(
180 {substPred.getPattern(), substPred.getReplacement()});
183 }
else if (rootNode->kind == PredCombinerKind::Concat) {
184 const auto &concatPred =
static_cast<const ConcatPred &
>(root);
185 rootNode->prefix = std::string(concatPred.getPrefix());
187 rootNode->suffix = std::string(concatPred.getSuffix());
192 auto combined =
static_cast<const CombinedPred &
>(root);
193 for (
const auto *record : combined.getChildren()) {
196 rootNode->children.push_back(childTree);
212 if (knownTruePreds.count(node->predicate) != 0) {
213 node->kind = PredCombinerKind::True;
214 node->children.clear();
217 if (knownFalsePreds.count(node->predicate) != 0) {
218 node->kind = PredCombinerKind::False;
219 node->children.clear();
234 if (node->kind == PredCombinerKind::SubstLeaves) {
238 if (node->kind == PredCombinerKind::And && node->children.empty()) {
239 node->kind = PredCombinerKind::True;
243 if (node->kind == PredCombinerKind::Or && node->children.empty()) {
244 node->kind = PredCombinerKind::False;
253 std::swap(node->children, children);
255 for (
auto &child : children) {
257 auto *simplifiedChild =
261 if (node->kind != PredCombinerKind::And &&
262 node->kind != PredCombinerKind::Or) {
263 node->children.push_back(simplifiedChild);
274 auto collapseKind = node->kind == PredCombinerKind::And
275 ? PredCombinerKind::False
276 : PredCombinerKind::True;
277 auto eraseKind = node->kind == PredCombinerKind::And
278 ? PredCombinerKind::True
279 : PredCombinerKind::False;
280 const auto &collapseList =
281 node->kind == PredCombinerKind::And ? knownFalsePreds : knownTruePreds;
282 const auto &eraseList =
283 node->kind == PredCombinerKind::And ? knownTruePreds : knownFalsePreds;
284 if (simplifiedChild->kind == collapseKind ||
285 collapseList.count(simplifiedChild->predicate) != 0) {
286 node->kind = collapseKind;
287 node->children.clear();
290 if (simplifiedChild->kind == eraseKind ||
291 eraseList.count(simplifiedChild->predicate) != 0) {
294 node->children.push_back(simplifiedChild);
302 const std::string &combiner,
304 if (children.empty())
307 auto size = children.size();
309 return children.front();
312 llvm::raw_string_ostream os(str);
313 os <<
'(' << children.front() <<
')';
314 for (
unsigned i = 1; i < size; ++i) {
315 os <<
' ' << combiner <<
" (" << children[i] <<
')';
322 assert(children.size() == 1 &&
"expected exactly one child predicate of Neg");
323 return (Twine(
"!(") + children.front() + Twine(
')')).str();
330 if (root.kind == PredCombinerKind::Leaf)
332 if (root.kind == PredCombinerKind::True)
334 if (root.kind == PredCombinerKind::False)
339 childExpressions.reserve(root.children.size());
340 for (
const auto &child : root.children)
344 if (root.kind == PredCombinerKind::And)
346 if (root.kind == PredCombinerKind::Or)
348 if (root.kind == PredCombinerKind::Not)
350 if (root.kind == PredCombinerKind::Concat) {
351 assert(childExpressions.size() == 1 &&
352 "ConcatPred should only have one child");
353 return root.prefix + childExpressions.front() + root.suffix;
357 if (root.kind == PredCombinerKind::SubstLeaves) {
358 assert(childExpressions.size() == 1 &&
359 "substitution predicate must have one child");
360 return childExpressions[0];
363 llvm::PrintFatalError(root.predicate->getLoc(),
"unsupported predicate kind");
367 SpecificBumpPtrAllocator<PredNode> allocator;
378 return def->getValueAsString(
"pattern");
382 return def->getValueAsString(
"replacement");
386 return def->getValueAsString(
"prefix");
390 return def->getValueAsString(
"suffix");
static std::string combineBinary(ArrayRef< std::string > children, const std::string &combiner, std::string init)
static std::string getCombinedCondition(const PredNode &root)
static PredCombinerKind getPredCombinerKind(const Pred &pred)
static void performSubstitutions(std::string &str, ArrayRef< Subst > substitutions)
Perform the given substitutions on 'str' in-place.
static PredNode * buildPredicateTree(const Pred &root, SpecificBumpPtrAllocator< PredNode > &allocator, ArrayRef< Subst > substitutions)
static PredNode * propagateGroundTruth(PredNode *node, const llvm::SmallPtrSetImpl< Pred * > &knownTruePreds, const llvm::SmallPtrSetImpl< Pred * > &knownFalsePreds)
static std::string combineNot(ArrayRef< std::string > children)
std::string getConditionImpl() const
CPred(const llvm::Record *record)
CombinedPred(const llvm::Record *record)
const llvm::Record * getCombinerDef() const
std::vector< const llvm::Record * > getChildren() const
std::string getConditionImpl() const
StringRef getSuffix() const
StringRef getPrefix() const
std::string getCondition() const
ArrayRef< SMLoc > getLoc() const
StringRef getReplacement() const
StringRef getPattern() const
Include the generated interface declarations.