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) {
243 std::swap(node->children, children);
245 for (
auto &child : children) {
247 auto *simplifiedChild =
251 if (node->kind != PredCombinerKind::And &&
252 node->kind != PredCombinerKind::Or) {
253 node->children.push_back(simplifiedChild);
264 auto collapseKind = node->kind == PredCombinerKind::And
265 ? PredCombinerKind::False
266 : PredCombinerKind::True;
267 auto eraseKind = node->kind == PredCombinerKind::And
268 ? PredCombinerKind::True
269 : PredCombinerKind::False;
270 const auto &collapseList =
271 node->kind == PredCombinerKind::And ? knownFalsePreds : knownTruePreds;
272 const auto &eraseList =
273 node->kind == PredCombinerKind::And ? knownTruePreds : knownFalsePreds;
274 if (simplifiedChild->kind == collapseKind ||
275 collapseList.count(simplifiedChild->predicate) != 0) {
276 node->kind = collapseKind;
277 node->children.clear();
280 if (simplifiedChild->kind == eraseKind ||
281 eraseList.count(simplifiedChild->predicate) != 0) {
284 node->children.push_back(simplifiedChild);
292 const std::string &combiner,
294 if (children.empty())
297 auto size = children.size();
299 return children.front();
302 llvm::raw_string_ostream os(str);
303 os <<
'(' << children.front() <<
')';
304 for (
unsigned i = 1; i < size; ++i) {
305 os <<
' ' << combiner <<
" (" << children[i] <<
')';
312 assert(children.size() == 1 &&
"expected exactly one child predicate of Neg");
313 return (Twine(
"!(") + children.front() + Twine(
')')).str();
320 if (root.kind == PredCombinerKind::Leaf)
322 if (root.kind == PredCombinerKind::True)
324 if (root.kind == PredCombinerKind::False)
329 childExpressions.reserve(root.children.size());
330 for (
const auto &child : root.children)
334 if (root.kind == PredCombinerKind::And)
336 if (root.kind == PredCombinerKind::Or)
338 if (root.kind == PredCombinerKind::Not)
340 if (root.kind == PredCombinerKind::Concat) {
341 assert(childExpressions.size() == 1 &&
342 "ConcatPred should only have one child");
343 return root.prefix + childExpressions.front() + root.suffix;
347 if (root.kind == PredCombinerKind::SubstLeaves) {
348 assert(childExpressions.size() == 1 &&
349 "substitution predicate must have one child");
350 return childExpressions[0];
353 llvm::PrintFatalError(root.predicate->getLoc(),
"unsupported predicate kind");
357 SpecificBumpPtrAllocator<PredNode> allocator;
368 return def->getValueAsString(
"pattern");
372 return def->getValueAsString(
"replacement");
376 return def->getValueAsString(
"prefix");
380 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.