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;
26 assert(
def->isSubClassOf(
"Pred") &&
27 "must be a subclass of TableGen 'Pred' class");
32 if (
const auto *defInit = dyn_cast_or_null<llvm::DefInit>(init))
33 def = defInit->getDef();
38 if (
def->isSubClassOf(
"CombinedPred"))
39 return static_cast<const CombinedPred *
>(
this)->getConditionImpl();
40 if (
def->isSubClassOf(
"CPred"))
42 llvm_unreachable(
"Pred::getCondition must be overridden in subclasses");
46 return def &&
def->isSubClassOf(
"CombinedPred");
52 assert(
def->isSubClassOf(
"CPred") &&
53 "must be a subclass of Tablegen 'CPred' class");
57 assert((!
def ||
def->isSubClassOf(
"CPred")) &&
58 "must be a subclass of Tablegen 'CPred' class");
63 assert(!
isNull() &&
"null predicate does not have a condition");
64 return std::string(
def->getValueAsString(
"predExpr"));
68 assert(
def->isSubClassOf(
"CombinedPred") &&
69 "must be a subclass of Tablegen 'CombinedPred' class");
73 assert((!
def ||
def->isSubClassOf(
"CombinedPred")) &&
74 "must be a subclass of Tablegen 'CombinedPred' class");
78 assert(
def->getValue(
"kind") &&
"CombinedPred must have a value 'kind'");
79 return def->getValueAsDef(
"kind");
83 assert(
def->getValue(
"children") &&
84 "CombinedPred must have a value 'children'");
85 return def->getValueAsListOfDefs(
"children");
90 enum class PredCombinerKind {
104 PredCombinerKind kind;
105 const Pred *predicate;
119 return PredCombinerKind::Leaf;
121 const auto &combinedPred =
static_cast<const CombinedPred &
>(pred);
123 combinedPred.getCombinerDef()->getName())
124 .Case(
"PredCombinerAnd", PredCombinerKind::And)
125 .Case(
"PredCombinerOr", PredCombinerKind::Or)
126 .Case(
"PredCombinerNot", PredCombinerKind::Not)
127 .Case(
"PredCombinerSubstLeaves", PredCombinerKind::SubstLeaves)
128 .Case(
"PredCombinerConcat", PredCombinerKind::Concat);
133 using Subst = std::pair<StringRef, StringRef>;
140 for (
const auto &subst : llvm::reverse(substitutions)) {
141 auto pos = str.find(std::string(subst.first));
142 while (pos != std::string::npos) {
143 str.replace(pos, subst.first.size(), std::string(subst.second));
146 pos += subst.second.size();
148 pos = str.find(std::string(subst.first), pos);
159 llvm::SpecificBumpPtrAllocator<PredNode> &allocator,
161 auto *rootNode = allocator.Allocate();
162 new (rootNode) PredNode;
164 rootNode->predicate = &root;
173 auto allSubstitutions = llvm::to_vector<4>(substitutions);
174 if (rootNode->kind == PredCombinerKind::SubstLeaves) {
176 allSubstitutions.push_back(
177 {substPred.getPattern(), substPred.getReplacement()});
180 }
else if (rootNode->kind == PredCombinerKind::Concat) {
181 const auto &concatPred =
static_cast<const ConcatPred &
>(root);
182 rootNode->prefix = std::string(concatPred.getPrefix());
184 rootNode->suffix = std::string(concatPred.getSuffix());
189 auto combined =
static_cast<const CombinedPred &
>(root);
190 for (
const auto *record : combined.getChildren()) {
193 rootNode->children.push_back(childTree);
209 if (knownTruePreds.count(node->predicate) != 0) {
210 node->kind = PredCombinerKind::True;
211 node->children.clear();
214 if (knownFalsePreds.count(node->predicate) != 0) {
215 node->kind = PredCombinerKind::False;
216 node->children.clear();
231 if (node->kind == PredCombinerKind::SubstLeaves) {
240 std::swap(node->children, children);
242 for (
auto &child : children) {
244 auto *simplifiedChild =
248 if (node->kind != PredCombinerKind::And &&
249 node->kind != PredCombinerKind::Or) {
250 node->children.push_back(simplifiedChild);
261 auto collapseKind = node->kind == PredCombinerKind::And
262 ? PredCombinerKind::False
263 : PredCombinerKind::True;
264 auto eraseKind = node->kind == PredCombinerKind::And
265 ? PredCombinerKind::True
266 : PredCombinerKind::False;
267 const auto &collapseList =
268 node->kind == PredCombinerKind::And ? knownFalsePreds : knownTruePreds;
269 const auto &eraseList =
270 node->kind == PredCombinerKind::And ? knownTruePreds : knownFalsePreds;
271 if (simplifiedChild->kind == collapseKind ||
272 collapseList.count(simplifiedChild->predicate) != 0) {
273 node->kind = collapseKind;
274 node->children.clear();
277 if (simplifiedChild->kind == eraseKind ||
278 eraseList.count(simplifiedChild->predicate) != 0) {
281 node->children.push_back(simplifiedChild);
289 const std::string &combiner,
291 if (children.empty())
294 auto size = children.size();
296 return children.front();
299 llvm::raw_string_ostream os(str);
300 os <<
'(' << children.front() <<
')';
301 for (
unsigned i = 1; i < size; ++i) {
302 os <<
' ' << combiner <<
" (" << children[i] <<
')';
309 assert(children.size() == 1 &&
"expected exactly one child predicate of Neg");
310 return (Twine(
"!(") + children.front() + Twine(
')')).str();
317 if (root.kind == PredCombinerKind::Leaf)
319 if (root.kind == PredCombinerKind::True)
321 if (root.kind == PredCombinerKind::False)
326 childExpressions.reserve(root.children.size());
327 for (
const auto &child : root.children)
331 if (root.kind == PredCombinerKind::And)
333 if (root.kind == PredCombinerKind::Or)
335 if (root.kind == PredCombinerKind::Not)
337 if (root.kind == PredCombinerKind::Concat) {
338 assert(childExpressions.size() == 1 &&
339 "ConcatPred should only have one child");
340 return root.prefix + childExpressions.front() + root.suffix;
344 if (root.kind == PredCombinerKind::SubstLeaves) {
345 assert(childExpressions.size() == 1 &&
346 "substitution predicate must have one child");
347 return childExpressions[0];
350 llvm::PrintFatalError(root.predicate->getLoc(),
"unsupported predicate kind");
354 llvm::SpecificBumpPtrAllocator<PredNode> allocator;
365 return def->getValueAsString(
"pattern");
369 return def->getValueAsString(
"replacement");
373 return def->getValueAsString(
"prefix");
377 return def->getValueAsString(
"suffix");
static PredNode * buildPredicateTree(const Pred &root, llvm::SpecificBumpPtrAllocator< PredNode > &allocator, ArrayRef< Subst > substitutions)
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 * 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)
const llvm::Record * getCombinerDef() const
std::vector< llvm::Record * > getChildren() const
std::string getConditionImpl() const
CombinedPred(const llvm::Record *record)
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.