18f249438SJacques Pienaar //===- Predicate.cpp - Predicate class ------------------------------------===//
28f249438SJacques Pienaar //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68f249438SJacques Pienaar //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
88f249438SJacques Pienaar //
98f249438SJacques Pienaar // Wrapper around predicates defined in TableGen.
108f249438SJacques Pienaar //
118f249438SJacques Pienaar //===----------------------------------------------------------------------===//
128f249438SJacques Pienaar
138f249438SJacques Pienaar #include "mlir/TableGen/Predicate.h"
144c0faef9SJacques Pienaar #include "llvm/ADT/SetVector.h"
1505b02bb9SAlex Zinenko #include "llvm/ADT/SmallPtrSet.h"
168f249438SJacques Pienaar #include "llvm/ADT/StringExtras.h"
1775e164f6Sserge-sans-paille #include "llvm/ADT/StringSwitch.h"
188f249438SJacques Pienaar #include "llvm/Support/FormatVariadic.h"
198f249438SJacques Pienaar #include "llvm/TableGen/Error.h"
208f249438SJacques Pienaar #include "llvm/TableGen/Record.h"
218f249438SJacques Pienaar
228f249438SJacques Pienaar using namespace mlir;
2312d16de5SRahul Joshi using namespace tblgen;
248f249438SJacques Pienaar
2544e9869fSAlex Zinenko // Construct a Predicate from a record.
Pred(const llvm::Record * record)2612d16de5SRahul Joshi Pred::Pred(const llvm::Record *record) : def(record) {
2744e9869fSAlex Zinenko assert(def->isSubClassOf("Pred") &&
2844e9869fSAlex Zinenko "must be a subclass of TableGen 'Pred' class");
2944e9869fSAlex Zinenko }
3044e9869fSAlex Zinenko
3144e9869fSAlex Zinenko // Construct a Predicate from an initializer.
Pred(const llvm::Init * init)3259d8740fSMehdi Amini Pred::Pred(const llvm::Init *init) {
3344e9869fSAlex Zinenko if (const auto *defInit = dyn_cast_or_null<llvm::DefInit>(init))
34b2cc2c34SLei Zhang def = defInit->getDef();
35b2cc2c34SLei Zhang }
36b2cc2c34SLei Zhang
getCondition() const3712d16de5SRahul Joshi std::string Pred::getCondition() const {
3805b02bb9SAlex Zinenko // Static dispatch to subclasses.
3905b02bb9SAlex Zinenko if (def->isSubClassOf("CombinedPred"))
4005b02bb9SAlex Zinenko return static_cast<const CombinedPred *>(this)->getConditionImpl();
4105b02bb9SAlex Zinenko if (def->isSubClassOf("CPred"))
4205b02bb9SAlex Zinenko return static_cast<const CPred *>(this)->getConditionImpl();
4305b02bb9SAlex Zinenko llvm_unreachable("Pred::getCondition must be overridden in subclasses");
4405b02bb9SAlex Zinenko }
4505b02bb9SAlex Zinenko
isCombined() const4612d16de5SRahul Joshi bool Pred::isCombined() const {
4705b02bb9SAlex Zinenko return def && def->isSubClassOf("CombinedPred");
4805b02bb9SAlex Zinenko }
4905b02bb9SAlex Zinenko
getLoc() const50*6842ec42SRiver Riddle ArrayRef<SMLoc> Pred::getLoc() const { return def->getLoc(); }
5105b02bb9SAlex Zinenko
CPred(const llvm::Record * record)5212d16de5SRahul Joshi CPred::CPred(const llvm::Record *record) : Pred(record) {
5305b02bb9SAlex Zinenko assert(def->isSubClassOf("CPred") &&
5405b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CPred' class");
5505b02bb9SAlex Zinenko }
5605b02bb9SAlex Zinenko
CPred(const llvm::Init * init)5712d16de5SRahul Joshi CPred::CPred(const llvm::Init *init) : Pred(init) {
5805b02bb9SAlex Zinenko assert((!def || def->isSubClassOf("CPred")) &&
5905b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CPred' class");
6005b02bb9SAlex Zinenko }
6105b02bb9SAlex Zinenko
6205b02bb9SAlex Zinenko // Get condition of the C Predicate.
getConditionImpl() const6312d16de5SRahul Joshi std::string CPred::getConditionImpl() const {
6444e9869fSAlex Zinenko assert(!isNull() && "null predicate does not have a condition");
65adcd0268SBenjamin Kramer return std::string(def->getValueAsString("predExpr"));
668f249438SJacques Pienaar }
6705b02bb9SAlex Zinenko
CombinedPred(const llvm::Record * record)6812d16de5SRahul Joshi CombinedPred::CombinedPred(const llvm::Record *record) : Pred(record) {
6905b02bb9SAlex Zinenko assert(def->isSubClassOf("CombinedPred") &&
7005b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CombinedPred' class");
7105b02bb9SAlex Zinenko }
7205b02bb9SAlex Zinenko
CombinedPred(const llvm::Init * init)7312d16de5SRahul Joshi CombinedPred::CombinedPred(const llvm::Init *init) : Pred(init) {
7405b02bb9SAlex Zinenko assert((!def || def->isSubClassOf("CombinedPred")) &&
7505b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CombinedPred' class");
7605b02bb9SAlex Zinenko }
7705b02bb9SAlex Zinenko
getCombinerDef() const7812d16de5SRahul Joshi const llvm::Record *CombinedPred::getCombinerDef() const {
7905b02bb9SAlex Zinenko assert(def->getValue("kind") && "CombinedPred must have a value 'kind'");
8005b02bb9SAlex Zinenko return def->getValueAsDef("kind");
8105b02bb9SAlex Zinenko }
8205b02bb9SAlex Zinenko
getChildren() const83ad5d7aceSMehdi Amini std::vector<llvm::Record *> CombinedPred::getChildren() const {
8405b02bb9SAlex Zinenko assert(def->getValue("children") &&
8505b02bb9SAlex Zinenko "CombinedPred must have a value 'children'");
8605b02bb9SAlex Zinenko return def->getValueAsListOfDefs("children");
8705b02bb9SAlex Zinenko }
8805b02bb9SAlex Zinenko
8905b02bb9SAlex Zinenko namespace {
9005b02bb9SAlex Zinenko // Kinds of nodes in a logical predicate tree.
9105b02bb9SAlex Zinenko enum class PredCombinerKind {
9205b02bb9SAlex Zinenko Leaf,
9305b02bb9SAlex Zinenko And,
9405b02bb9SAlex Zinenko Or,
9505b02bb9SAlex Zinenko Not,
9605b02bb9SAlex Zinenko SubstLeaves,
97b5235d1aSLei Zhang Concat,
9805b02bb9SAlex Zinenko // Special kinds that are used in simplification.
9905b02bb9SAlex Zinenko False,
10005b02bb9SAlex Zinenko True
10105b02bb9SAlex Zinenko };
10205b02bb9SAlex Zinenko
10305b02bb9SAlex Zinenko // A node in a logical predicate tree.
10405b02bb9SAlex Zinenko struct PredNode {
10505b02bb9SAlex Zinenko PredCombinerKind kind;
10612d16de5SRahul Joshi const Pred *predicate;
10705b02bb9SAlex Zinenko SmallVector<PredNode *, 4> children;
10805b02bb9SAlex Zinenko std::string expr;
109b5235d1aSLei Zhang
110b5235d1aSLei Zhang // Prefix and suffix are used by ConcatPred.
111b5235d1aSLei Zhang std::string prefix;
112b5235d1aSLei Zhang std::string suffix;
11305b02bb9SAlex Zinenko };
114be0a7e9fSMehdi Amini } // namespace
11505b02bb9SAlex Zinenko
11605b02bb9SAlex Zinenko // Get a predicate tree node kind based on the kind used in the predicate
11705b02bb9SAlex Zinenko // TableGen record.
getPredCombinerKind(const Pred & pred)11812d16de5SRahul Joshi static PredCombinerKind getPredCombinerKind(const Pred &pred) {
11905b02bb9SAlex Zinenko if (!pred.isCombined())
12005b02bb9SAlex Zinenko return PredCombinerKind::Leaf;
12105b02bb9SAlex Zinenko
12212d16de5SRahul Joshi const auto &combinedPred = static_cast<const CombinedPred &>(pred);
123cc83dc19SChristian Sigg return StringSwitch<PredCombinerKind>(
12405b02bb9SAlex Zinenko combinedPred.getCombinerDef()->getName())
12505b02bb9SAlex Zinenko .Case("PredCombinerAnd", PredCombinerKind::And)
12605b02bb9SAlex Zinenko .Case("PredCombinerOr", PredCombinerKind::Or)
12705b02bb9SAlex Zinenko .Case("PredCombinerNot", PredCombinerKind::Not)
128b5235d1aSLei Zhang .Case("PredCombinerSubstLeaves", PredCombinerKind::SubstLeaves)
129b5235d1aSLei Zhang .Case("PredCombinerConcat", PredCombinerKind::Concat);
13005b02bb9SAlex Zinenko }
13105b02bb9SAlex Zinenko
13205b02bb9SAlex Zinenko namespace {
13305b02bb9SAlex Zinenko // Substitution<pattern, replacement>.
13405b02bb9SAlex Zinenko using Subst = std::pair<StringRef, StringRef>;
135be0a7e9fSMehdi Amini } // namespace
13605b02bb9SAlex Zinenko
1373a833a0eSRiver Riddle /// Perform the given substitutions on 'str' in-place.
performSubstitutions(std::string & str,ArrayRef<Subst> substitutions)1383a833a0eSRiver Riddle static void performSubstitutions(std::string &str,
1393a833a0eSRiver Riddle ArrayRef<Subst> substitutions) {
1403a833a0eSRiver Riddle // Apply all parent substitutions from innermost to outermost.
1413a833a0eSRiver Riddle for (const auto &subst : llvm::reverse(substitutions)) {
1423a833a0eSRiver Riddle auto pos = str.find(std::string(subst.first));
1433a833a0eSRiver Riddle while (pos != std::string::npos) {
1443a833a0eSRiver Riddle str.replace(pos, subst.first.size(), std::string(subst.second));
1453a833a0eSRiver Riddle // Skip the newly inserted substring, which itself may consider the
1463a833a0eSRiver Riddle // pattern to match.
1473a833a0eSRiver Riddle pos += subst.second.size();
1483a833a0eSRiver Riddle // Find the next possible match position.
1493a833a0eSRiver Riddle pos = str.find(std::string(subst.first), pos);
1503a833a0eSRiver Riddle }
1513a833a0eSRiver Riddle }
1523a833a0eSRiver Riddle }
1533a833a0eSRiver Riddle
15405b02bb9SAlex Zinenko // Build the predicate tree starting from the top-level predicate, which may
15505b02bb9SAlex Zinenko // have children, and perform leaf substitutions inplace. Note that after
15605b02bb9SAlex Zinenko // substitution, nodes are still pointing to the original TableGen record.
15705b02bb9SAlex Zinenko // All nodes are created within "allocator".
158b68b8be8SBenjamin Kramer static PredNode *
buildPredicateTree(const Pred & root,llvm::SpecificBumpPtrAllocator<PredNode> & allocator,ArrayRef<Subst> substitutions)15912d16de5SRahul Joshi buildPredicateTree(const Pred &root,
160b68b8be8SBenjamin Kramer llvm::SpecificBumpPtrAllocator<PredNode> &allocator,
16105b02bb9SAlex Zinenko ArrayRef<Subst> substitutions) {
162b68b8be8SBenjamin Kramer auto *rootNode = allocator.Allocate();
16305b02bb9SAlex Zinenko new (rootNode) PredNode;
16405b02bb9SAlex Zinenko rootNode->kind = getPredCombinerKind(root);
16505b02bb9SAlex Zinenko rootNode->predicate = &root;
16605b02bb9SAlex Zinenko if (!root.isCombined()) {
16705b02bb9SAlex Zinenko rootNode->expr = root.getCondition();
1683a833a0eSRiver Riddle performSubstitutions(rootNode->expr, substitutions);
16905b02bb9SAlex Zinenko return rootNode;
17005b02bb9SAlex Zinenko }
17105b02bb9SAlex Zinenko
17205b02bb9SAlex Zinenko // If the current combined predicate is a leaf substitution, append it to the
1738bfedb3cSKazuaki Ishizaki // list before continuing.
17405b02bb9SAlex Zinenko auto allSubstitutions = llvm::to_vector<4>(substitutions);
17505b02bb9SAlex Zinenko if (rootNode->kind == PredCombinerKind::SubstLeaves) {
17612d16de5SRahul Joshi const auto &substPred = static_cast<const SubstLeavesPred &>(root);
17705b02bb9SAlex Zinenko allSubstitutions.push_back(
17805b02bb9SAlex Zinenko {substPred.getPattern(), substPred.getReplacement()});
1793a833a0eSRiver Riddle
180b5235d1aSLei Zhang // If the current predicate is a ConcatPred, record the prefix and suffix.
1813a833a0eSRiver Riddle } else if (rootNode->kind == PredCombinerKind::Concat) {
18212d16de5SRahul Joshi const auto &concatPred = static_cast<const ConcatPred &>(root);
183adcd0268SBenjamin Kramer rootNode->prefix = std::string(concatPred.getPrefix());
1843a833a0eSRiver Riddle performSubstitutions(rootNode->prefix, substitutions);
185adcd0268SBenjamin Kramer rootNode->suffix = std::string(concatPred.getSuffix());
1863a833a0eSRiver Riddle performSubstitutions(rootNode->suffix, substitutions);
187b5235d1aSLei Zhang }
18805b02bb9SAlex Zinenko
18905b02bb9SAlex Zinenko // Build child subtrees.
19012d16de5SRahul Joshi auto combined = static_cast<const CombinedPred &>(root);
19105b02bb9SAlex Zinenko for (const auto *record : combined.getChildren()) {
19202b6fb21SMehdi Amini auto *childTree =
19312d16de5SRahul Joshi buildPredicateTree(Pred(record), allocator, allSubstitutions);
19405b02bb9SAlex Zinenko rootNode->children.push_back(childTree);
19505b02bb9SAlex Zinenko }
19605b02bb9SAlex Zinenko return rootNode;
19705b02bb9SAlex Zinenko }
19805b02bb9SAlex Zinenko
19905b02bb9SAlex Zinenko // Simplify a predicate tree rooted at "node" using the predicates that are
20005b02bb9SAlex Zinenko // known to be true(false). For AND(OR) combined predicates, if any of the
20105b02bb9SAlex Zinenko // children is known to be false(true), the result is also false(true).
20205b02bb9SAlex Zinenko // Furthermore, for AND(OR) combined predicates, children that are known to be
20305b02bb9SAlex Zinenko // true(false) don't have to be checked dynamically.
20412d16de5SRahul Joshi static PredNode *
propagateGroundTruth(PredNode * node,const llvm::SmallPtrSetImpl<Pred * > & knownTruePreds,const llvm::SmallPtrSetImpl<Pred * > & knownFalsePreds)20512d16de5SRahul Joshi propagateGroundTruth(PredNode *node,
20612d16de5SRahul Joshi const llvm::SmallPtrSetImpl<Pred *> &knownTruePreds,
20712d16de5SRahul Joshi const llvm::SmallPtrSetImpl<Pred *> &knownFalsePreds) {
20805b02bb9SAlex Zinenko // If the current predicate is known to be true or false, change the kind of
20905b02bb9SAlex Zinenko // the node and return immediately.
21005b02bb9SAlex Zinenko if (knownTruePreds.count(node->predicate) != 0) {
21105b02bb9SAlex Zinenko node->kind = PredCombinerKind::True;
21205b02bb9SAlex Zinenko node->children.clear();
21305b02bb9SAlex Zinenko return node;
21405b02bb9SAlex Zinenko }
21505b02bb9SAlex Zinenko if (knownFalsePreds.count(node->predicate) != 0) {
21605b02bb9SAlex Zinenko node->kind = PredCombinerKind::False;
21705b02bb9SAlex Zinenko node->children.clear();
21805b02bb9SAlex Zinenko return node;
21905b02bb9SAlex Zinenko }
22005b02bb9SAlex Zinenko
22105b02bb9SAlex Zinenko // If the current node is a substitution, stop recursion now.
22205b02bb9SAlex Zinenko // The expressions in the leaves below this node were rewritten, but the nodes
22305b02bb9SAlex Zinenko // still point to the original predicate records. While the original
22405b02bb9SAlex Zinenko // predicate may be known to be true or false, it is not necessarily the case
22505b02bb9SAlex Zinenko // after rewriting.
2269db53a18SRiver Riddle // TODO: we can support ground truth for rewritten
22705b02bb9SAlex Zinenko // predicates by either (a) having our own unique'ing of the predicates
22805b02bb9SAlex Zinenko // instead of relying on TableGen record pointers or (b) taking ground truth
2298bfedb3cSKazuaki Ishizaki // values optionally prefixed with a list of substitutions to apply, e.g.
23005b02bb9SAlex Zinenko // "predX is true by itself as well as predSubY leaf substitution had been
23105b02bb9SAlex Zinenko // applied to it".
23205b02bb9SAlex Zinenko if (node->kind == PredCombinerKind::SubstLeaves) {
23305b02bb9SAlex Zinenko return node;
23405b02bb9SAlex Zinenko }
23505b02bb9SAlex Zinenko
23605b02bb9SAlex Zinenko // Otherwise, look at child nodes.
23705b02bb9SAlex Zinenko
23805b02bb9SAlex Zinenko // Move child nodes into some local variable so that they can be optimized
23905b02bb9SAlex Zinenko // separately and re-added if necessary.
24005b02bb9SAlex Zinenko llvm::SmallVector<PredNode *, 4> children;
24105b02bb9SAlex Zinenko std::swap(node->children, children);
24205b02bb9SAlex Zinenko
24305b02bb9SAlex Zinenko for (auto &child : children) {
24405b02bb9SAlex Zinenko // First, simplify the child. This maintains the predicate as it was.
24502b6fb21SMehdi Amini auto *simplifiedChild =
24605b02bb9SAlex Zinenko propagateGroundTruth(child, knownTruePreds, knownFalsePreds);
24705b02bb9SAlex Zinenko
24805b02bb9SAlex Zinenko // Just add the child if we don't know how to simplify the current node.
24905b02bb9SAlex Zinenko if (node->kind != PredCombinerKind::And &&
25005b02bb9SAlex Zinenko node->kind != PredCombinerKind::Or) {
25105b02bb9SAlex Zinenko node->children.push_back(simplifiedChild);
25205b02bb9SAlex Zinenko continue;
25305b02bb9SAlex Zinenko }
25405b02bb9SAlex Zinenko
25505b02bb9SAlex Zinenko // Second, based on the type define which known values of child predicates
25605b02bb9SAlex Zinenko // immediately collapse this predicate to a known value, and which others
25705b02bb9SAlex Zinenko // may be safely ignored.
25805b02bb9SAlex Zinenko // OR(..., True, ...) = True
25905b02bb9SAlex Zinenko // OR(..., False, ...) = OR(..., ...)
26005b02bb9SAlex Zinenko // AND(..., False, ...) = False
26105b02bb9SAlex Zinenko // AND(..., True, ...) = AND(..., ...)
26205b02bb9SAlex Zinenko auto collapseKind = node->kind == PredCombinerKind::And
26305b02bb9SAlex Zinenko ? PredCombinerKind::False
26405b02bb9SAlex Zinenko : PredCombinerKind::True;
26505b02bb9SAlex Zinenko auto eraseKind = node->kind == PredCombinerKind::And
26605b02bb9SAlex Zinenko ? PredCombinerKind::True
26705b02bb9SAlex Zinenko : PredCombinerKind::False;
26805b02bb9SAlex Zinenko const auto &collapseList =
26905b02bb9SAlex Zinenko node->kind == PredCombinerKind::And ? knownFalsePreds : knownTruePreds;
27005b02bb9SAlex Zinenko const auto &eraseList =
27105b02bb9SAlex Zinenko node->kind == PredCombinerKind::And ? knownTruePreds : knownFalsePreds;
27205b02bb9SAlex Zinenko if (simplifiedChild->kind == collapseKind ||
27305b02bb9SAlex Zinenko collapseList.count(simplifiedChild->predicate) != 0) {
27405b02bb9SAlex Zinenko node->kind = collapseKind;
27505b02bb9SAlex Zinenko node->children.clear();
27605b02bb9SAlex Zinenko return node;
27702b6fb21SMehdi Amini }
27802b6fb21SMehdi Amini if (simplifiedChild->kind == eraseKind ||
27905b02bb9SAlex Zinenko eraseList.count(simplifiedChild->predicate) != 0) {
28005b02bb9SAlex Zinenko continue;
28105b02bb9SAlex Zinenko }
28205b02bb9SAlex Zinenko node->children.push_back(simplifiedChild);
28305b02bb9SAlex Zinenko }
28405b02bb9SAlex Zinenko return node;
28505b02bb9SAlex Zinenko }
28605b02bb9SAlex Zinenko
28705b02bb9SAlex Zinenko // Combine a list of predicate expressions using a binary combiner. If a list
28805b02bb9SAlex Zinenko // is empty, return "init".
combineBinary(ArrayRef<std::string> children,const std::string & combiner,std::string init)28905b02bb9SAlex Zinenko static std::string combineBinary(ArrayRef<std::string> children,
2901fc096afSMehdi Amini const std::string &combiner,
2911fc096afSMehdi Amini std::string init) {
29205b02bb9SAlex Zinenko if (children.empty())
29305b02bb9SAlex Zinenko return init;
29405b02bb9SAlex Zinenko
29505b02bb9SAlex Zinenko auto size = children.size();
29605b02bb9SAlex Zinenko if (size == 1)
29705b02bb9SAlex Zinenko return children.front();
29805b02bb9SAlex Zinenko
29905b02bb9SAlex Zinenko std::string str;
30005b02bb9SAlex Zinenko llvm::raw_string_ostream os(str);
30105b02bb9SAlex Zinenko os << '(' << children.front() << ')';
30205b02bb9SAlex Zinenko for (unsigned i = 1; i < size; ++i) {
30305b02bb9SAlex Zinenko os << ' ' << combiner << " (" << children[i] << ')';
30405b02bb9SAlex Zinenko }
30505b02bb9SAlex Zinenko return os.str();
30605b02bb9SAlex Zinenko }
30705b02bb9SAlex Zinenko
30805b02bb9SAlex Zinenko // Prepend negation to the only condition in the predicate expression list.
combineNot(ArrayRef<std::string> children)30905b02bb9SAlex Zinenko static std::string combineNot(ArrayRef<std::string> children) {
31005b02bb9SAlex Zinenko assert(children.size() == 1 && "expected exactly one child predicate of Neg");
31105b02bb9SAlex Zinenko return (Twine("!(") + children.front() + Twine(')')).str();
31205b02bb9SAlex Zinenko }
31305b02bb9SAlex Zinenko
31405b02bb9SAlex Zinenko // Recursively traverse the predicate tree in depth-first post-order and build
31505b02bb9SAlex Zinenko // the final expression.
getCombinedCondition(const PredNode & root)31605b02bb9SAlex Zinenko static std::string getCombinedCondition(const PredNode &root) {
31705b02bb9SAlex Zinenko // Immediately return for non-combiner predicates that don't have children.
31805b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::Leaf)
31905b02bb9SAlex Zinenko return root.expr;
32005b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::True)
32105b02bb9SAlex Zinenko return "true";
32205b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::False)
32305b02bb9SAlex Zinenko return "false";
32405b02bb9SAlex Zinenko
32505b02bb9SAlex Zinenko // Recurse into children.
32605b02bb9SAlex Zinenko llvm::SmallVector<std::string, 4> childExpressions;
32705b02bb9SAlex Zinenko childExpressions.reserve(root.children.size());
32805b02bb9SAlex Zinenko for (const auto &child : root.children)
32905b02bb9SAlex Zinenko childExpressions.push_back(getCombinedCondition(*child));
33005b02bb9SAlex Zinenko
33105b02bb9SAlex Zinenko // Combine the expressions based on the predicate node kind.
33205b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::And)
33305b02bb9SAlex Zinenko return combineBinary(childExpressions, "&&", "true");
33405b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::Or)
33505b02bb9SAlex Zinenko return combineBinary(childExpressions, "||", "false");
33605b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::Not)
33705b02bb9SAlex Zinenko return combineNot(childExpressions);
338b5235d1aSLei Zhang if (root.kind == PredCombinerKind::Concat) {
339b5235d1aSLei Zhang assert(childExpressions.size() == 1 &&
340b5235d1aSLei Zhang "ConcatPred should only have one child");
341b5235d1aSLei Zhang return root.prefix + childExpressions.front() + root.suffix;
342b5235d1aSLei Zhang }
34305b02bb9SAlex Zinenko
34405b02bb9SAlex Zinenko // Substitutions were applied before so just ignore them.
34505b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::SubstLeaves) {
34605b02bb9SAlex Zinenko assert(childExpressions.size() == 1 &&
34705b02bb9SAlex Zinenko "substitution predicate must have one child");
34805b02bb9SAlex Zinenko return childExpressions[0];
34905b02bb9SAlex Zinenko }
35005b02bb9SAlex Zinenko
35105b02bb9SAlex Zinenko llvm::PrintFatalError(root.predicate->getLoc(), "unsupported predicate kind");
35205b02bb9SAlex Zinenko }
35305b02bb9SAlex Zinenko
getConditionImpl() const35412d16de5SRahul Joshi std::string CombinedPred::getConditionImpl() const {
355b68b8be8SBenjamin Kramer llvm::SpecificBumpPtrAllocator<PredNode> allocator;
35602b6fb21SMehdi Amini auto *predicateTree = buildPredicateTree(*this, allocator, {});
35712d16de5SRahul Joshi predicateTree =
35812d16de5SRahul Joshi propagateGroundTruth(predicateTree,
35912d16de5SRahul Joshi /*knownTruePreds=*/llvm::SmallPtrSet<Pred *, 2>(),
36012d16de5SRahul Joshi /*knownFalsePreds=*/llvm::SmallPtrSet<Pred *, 2>());
36105b02bb9SAlex Zinenko
36205b02bb9SAlex Zinenko return getCombinedCondition(*predicateTree);
36305b02bb9SAlex Zinenko }
36405b02bb9SAlex Zinenko
getPattern() const36512d16de5SRahul Joshi StringRef SubstLeavesPred::getPattern() const {
36605b02bb9SAlex Zinenko return def->getValueAsString("pattern");
36705b02bb9SAlex Zinenko }
36805b02bb9SAlex Zinenko
getReplacement() const36912d16de5SRahul Joshi StringRef SubstLeavesPred::getReplacement() const {
37005b02bb9SAlex Zinenko return def->getValueAsString("replacement");
37105b02bb9SAlex Zinenko }
372b5235d1aSLei Zhang
getPrefix() const37312d16de5SRahul Joshi StringRef ConcatPred::getPrefix() const {
374b5235d1aSLei Zhang return def->getValueAsString("prefix");
375b5235d1aSLei Zhang }
376b5235d1aSLei Zhang
getSuffix() const37712d16de5SRahul Joshi StringRef ConcatPred::getSuffix() const {
378b5235d1aSLei Zhang return def->getValueAsString("suffix");
379b5235d1aSLei Zhang }
380