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" 1405b02bb9SAlex Zinenko #include "llvm/ADT/SmallPtrSet.h" 158f249438SJacques Pienaar #include "llvm/ADT/StringExtras.h" 1675e164f6Sserge-sans-paille #include "llvm/ADT/StringSwitch.h" 178f249438SJacques Pienaar #include "llvm/Support/FormatVariadic.h" 188f249438SJacques Pienaar #include "llvm/TableGen/Error.h" 198f249438SJacques Pienaar #include "llvm/TableGen/Record.h" 208f249438SJacques Pienaar 218f249438SJacques Pienaar using namespace mlir; 2212d16de5SRahul Joshi using namespace tblgen; 23659192b1SRahul Joshi using llvm::Init; 24659192b1SRahul Joshi using llvm::Record; 25659192b1SRahul Joshi using llvm::SpecificBumpPtrAllocator; 268f249438SJacques Pienaar 2744e9869fSAlex Zinenko // Construct a Predicate from a record. 28659192b1SRahul Joshi Pred::Pred(const Record *record) : def(record) { 2944e9869fSAlex Zinenko assert(def->isSubClassOf("Pred") && 3044e9869fSAlex Zinenko "must be a subclass of TableGen 'Pred' class"); 3144e9869fSAlex Zinenko } 3244e9869fSAlex Zinenko 3344e9869fSAlex Zinenko // Construct a Predicate from an initializer. 34659192b1SRahul Joshi Pred::Pred(const Init *init) { 3544e9869fSAlex Zinenko if (const auto *defInit = dyn_cast_or_null<llvm::DefInit>(init)) 36b2cc2c34SLei Zhang def = defInit->getDef(); 37b2cc2c34SLei Zhang } 38b2cc2c34SLei Zhang 3912d16de5SRahul Joshi std::string Pred::getCondition() const { 4005b02bb9SAlex Zinenko // Static dispatch to subclasses. 4105b02bb9SAlex Zinenko if (def->isSubClassOf("CombinedPred")) 4205b02bb9SAlex Zinenko return static_cast<const CombinedPred *>(this)->getConditionImpl(); 4305b02bb9SAlex Zinenko if (def->isSubClassOf("CPred")) 4405b02bb9SAlex Zinenko return static_cast<const CPred *>(this)->getConditionImpl(); 4505b02bb9SAlex Zinenko llvm_unreachable("Pred::getCondition must be overridden in subclasses"); 4605b02bb9SAlex Zinenko } 4705b02bb9SAlex Zinenko 4812d16de5SRahul Joshi bool Pred::isCombined() const { 4905b02bb9SAlex Zinenko return def && def->isSubClassOf("CombinedPred"); 5005b02bb9SAlex Zinenko } 5105b02bb9SAlex Zinenko 526842ec42SRiver Riddle ArrayRef<SMLoc> Pred::getLoc() const { return def->getLoc(); } 5305b02bb9SAlex Zinenko 54659192b1SRahul Joshi CPred::CPred(const Record *record) : Pred(record) { 5505b02bb9SAlex Zinenko assert(def->isSubClassOf("CPred") && 5605b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CPred' class"); 5705b02bb9SAlex Zinenko } 5805b02bb9SAlex Zinenko 59659192b1SRahul Joshi CPred::CPred(const Init *init) : Pred(init) { 6005b02bb9SAlex Zinenko assert((!def || def->isSubClassOf("CPred")) && 6105b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CPred' class"); 6205b02bb9SAlex Zinenko } 6305b02bb9SAlex Zinenko 6405b02bb9SAlex Zinenko // Get condition of the C Predicate. 6512d16de5SRahul Joshi std::string CPred::getConditionImpl() const { 6644e9869fSAlex Zinenko assert(!isNull() && "null predicate does not have a condition"); 67adcd0268SBenjamin Kramer return std::string(def->getValueAsString("predExpr")); 688f249438SJacques Pienaar } 6905b02bb9SAlex Zinenko 70659192b1SRahul Joshi CombinedPred::CombinedPred(const Record *record) : Pred(record) { 7105b02bb9SAlex Zinenko assert(def->isSubClassOf("CombinedPred") && 7205b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CombinedPred' class"); 7305b02bb9SAlex Zinenko } 7405b02bb9SAlex Zinenko 75659192b1SRahul Joshi CombinedPred::CombinedPred(const Init *init) : Pred(init) { 7605b02bb9SAlex Zinenko assert((!def || def->isSubClassOf("CombinedPred")) && 7705b02bb9SAlex Zinenko "must be a subclass of Tablegen 'CombinedPred' class"); 7805b02bb9SAlex Zinenko } 7905b02bb9SAlex Zinenko 80659192b1SRahul Joshi const Record *CombinedPred::getCombinerDef() const { 8105b02bb9SAlex Zinenko assert(def->getValue("kind") && "CombinedPred must have a value 'kind'"); 8205b02bb9SAlex Zinenko return def->getValueAsDef("kind"); 8305b02bb9SAlex Zinenko } 8405b02bb9SAlex Zinenko 85659192b1SRahul Joshi std::vector<const Record *> CombinedPred::getChildren() const { 8605b02bb9SAlex Zinenko assert(def->getValue("children") && 8705b02bb9SAlex Zinenko "CombinedPred must have a value 'children'"); 88a140931bSRahul Joshi return def->getValueAsListOfDefs("children"); 8905b02bb9SAlex Zinenko } 9005b02bb9SAlex Zinenko 9105b02bb9SAlex Zinenko namespace { 9205b02bb9SAlex Zinenko // Kinds of nodes in a logical predicate tree. 9305b02bb9SAlex Zinenko enum class PredCombinerKind { 9405b02bb9SAlex Zinenko Leaf, 9505b02bb9SAlex Zinenko And, 9605b02bb9SAlex Zinenko Or, 9705b02bb9SAlex Zinenko Not, 9805b02bb9SAlex Zinenko SubstLeaves, 99b5235d1aSLei Zhang Concat, 10005b02bb9SAlex Zinenko // Special kinds that are used in simplification. 10105b02bb9SAlex Zinenko False, 10205b02bb9SAlex Zinenko True 10305b02bb9SAlex Zinenko }; 10405b02bb9SAlex Zinenko 10505b02bb9SAlex Zinenko // A node in a logical predicate tree. 10605b02bb9SAlex Zinenko struct PredNode { 10705b02bb9SAlex Zinenko PredCombinerKind kind; 10812d16de5SRahul Joshi const Pred *predicate; 10905b02bb9SAlex Zinenko SmallVector<PredNode *, 4> children; 11005b02bb9SAlex Zinenko std::string expr; 111b5235d1aSLei Zhang 112b5235d1aSLei Zhang // Prefix and suffix are used by ConcatPred. 113b5235d1aSLei Zhang std::string prefix; 114b5235d1aSLei Zhang std::string suffix; 11505b02bb9SAlex Zinenko }; 116be0a7e9fSMehdi Amini } // namespace 11705b02bb9SAlex Zinenko 11805b02bb9SAlex Zinenko // Get a predicate tree node kind based on the kind used in the predicate 11905b02bb9SAlex Zinenko // TableGen record. 12012d16de5SRahul Joshi static PredCombinerKind getPredCombinerKind(const Pred &pred) { 12105b02bb9SAlex Zinenko if (!pred.isCombined()) 12205b02bb9SAlex Zinenko return PredCombinerKind::Leaf; 12305b02bb9SAlex Zinenko 12412d16de5SRahul Joshi const auto &combinedPred = static_cast<const CombinedPred &>(pred); 125cc83dc19SChristian Sigg return StringSwitch<PredCombinerKind>( 12605b02bb9SAlex Zinenko combinedPred.getCombinerDef()->getName()) 12705b02bb9SAlex Zinenko .Case("PredCombinerAnd", PredCombinerKind::And) 12805b02bb9SAlex Zinenko .Case("PredCombinerOr", PredCombinerKind::Or) 12905b02bb9SAlex Zinenko .Case("PredCombinerNot", PredCombinerKind::Not) 130b5235d1aSLei Zhang .Case("PredCombinerSubstLeaves", PredCombinerKind::SubstLeaves) 131b5235d1aSLei Zhang .Case("PredCombinerConcat", PredCombinerKind::Concat); 13205b02bb9SAlex Zinenko } 13305b02bb9SAlex Zinenko 13405b02bb9SAlex Zinenko namespace { 13505b02bb9SAlex Zinenko // Substitution<pattern, replacement>. 13605b02bb9SAlex Zinenko using Subst = std::pair<StringRef, StringRef>; 137be0a7e9fSMehdi Amini } // namespace 13805b02bb9SAlex Zinenko 1393a833a0eSRiver Riddle /// Perform the given substitutions on 'str' in-place. 1403a833a0eSRiver Riddle static void performSubstitutions(std::string &str, 1413a833a0eSRiver Riddle ArrayRef<Subst> substitutions) { 1423a833a0eSRiver Riddle // Apply all parent substitutions from innermost to outermost. 1433a833a0eSRiver Riddle for (const auto &subst : llvm::reverse(substitutions)) { 1443a833a0eSRiver Riddle auto pos = str.find(std::string(subst.first)); 1453a833a0eSRiver Riddle while (pos != std::string::npos) { 1463a833a0eSRiver Riddle str.replace(pos, subst.first.size(), std::string(subst.second)); 1473a833a0eSRiver Riddle // Skip the newly inserted substring, which itself may consider the 1483a833a0eSRiver Riddle // pattern to match. 1493a833a0eSRiver Riddle pos += subst.second.size(); 1503a833a0eSRiver Riddle // Find the next possible match position. 1513a833a0eSRiver Riddle pos = str.find(std::string(subst.first), pos); 1523a833a0eSRiver Riddle } 1533a833a0eSRiver Riddle } 1543a833a0eSRiver Riddle } 1553a833a0eSRiver Riddle 15605b02bb9SAlex Zinenko // Build the predicate tree starting from the top-level predicate, which may 15705b02bb9SAlex Zinenko // have children, and perform leaf substitutions inplace. Note that after 15805b02bb9SAlex Zinenko // substitution, nodes are still pointing to the original TableGen record. 15905b02bb9SAlex Zinenko // All nodes are created within "allocator". 160b68b8be8SBenjamin Kramer static PredNode * 16112d16de5SRahul Joshi buildPredicateTree(const Pred &root, 162659192b1SRahul Joshi SpecificBumpPtrAllocator<PredNode> &allocator, 16305b02bb9SAlex Zinenko ArrayRef<Subst> substitutions) { 164b68b8be8SBenjamin Kramer auto *rootNode = allocator.Allocate(); 16505b02bb9SAlex Zinenko new (rootNode) PredNode; 16605b02bb9SAlex Zinenko rootNode->kind = getPredCombinerKind(root); 16705b02bb9SAlex Zinenko rootNode->predicate = &root; 16805b02bb9SAlex Zinenko if (!root.isCombined()) { 16905b02bb9SAlex Zinenko rootNode->expr = root.getCondition(); 1703a833a0eSRiver Riddle performSubstitutions(rootNode->expr, substitutions); 17105b02bb9SAlex Zinenko return rootNode; 17205b02bb9SAlex Zinenko } 17305b02bb9SAlex Zinenko 17405b02bb9SAlex Zinenko // If the current combined predicate is a leaf substitution, append it to the 1758bfedb3cSKazuaki Ishizaki // list before continuing. 17605b02bb9SAlex Zinenko auto allSubstitutions = llvm::to_vector<4>(substitutions); 17705b02bb9SAlex Zinenko if (rootNode->kind == PredCombinerKind::SubstLeaves) { 17812d16de5SRahul Joshi const auto &substPred = static_cast<const SubstLeavesPred &>(root); 17905b02bb9SAlex Zinenko allSubstitutions.push_back( 18005b02bb9SAlex Zinenko {substPred.getPattern(), substPred.getReplacement()}); 1813a833a0eSRiver Riddle 182b5235d1aSLei Zhang // If the current predicate is a ConcatPred, record the prefix and suffix. 1833a833a0eSRiver Riddle } else if (rootNode->kind == PredCombinerKind::Concat) { 18412d16de5SRahul Joshi const auto &concatPred = static_cast<const ConcatPred &>(root); 185adcd0268SBenjamin Kramer rootNode->prefix = std::string(concatPred.getPrefix()); 1863a833a0eSRiver Riddle performSubstitutions(rootNode->prefix, substitutions); 187adcd0268SBenjamin Kramer rootNode->suffix = std::string(concatPred.getSuffix()); 1883a833a0eSRiver Riddle performSubstitutions(rootNode->suffix, substitutions); 189b5235d1aSLei Zhang } 19005b02bb9SAlex Zinenko 19105b02bb9SAlex Zinenko // Build child subtrees. 19212d16de5SRahul Joshi auto combined = static_cast<const CombinedPred &>(root); 19305b02bb9SAlex Zinenko for (const auto *record : combined.getChildren()) { 19402b6fb21SMehdi Amini auto *childTree = 19512d16de5SRahul Joshi buildPredicateTree(Pred(record), allocator, allSubstitutions); 19605b02bb9SAlex Zinenko rootNode->children.push_back(childTree); 19705b02bb9SAlex Zinenko } 19805b02bb9SAlex Zinenko return rootNode; 19905b02bb9SAlex Zinenko } 20005b02bb9SAlex Zinenko 20105b02bb9SAlex Zinenko // Simplify a predicate tree rooted at "node" using the predicates that are 20205b02bb9SAlex Zinenko // known to be true(false). For AND(OR) combined predicates, if any of the 20305b02bb9SAlex Zinenko // children is known to be false(true), the result is also false(true). 20405b02bb9SAlex Zinenko // Furthermore, for AND(OR) combined predicates, children that are known to be 20505b02bb9SAlex Zinenko // true(false) don't have to be checked dynamically. 20612d16de5SRahul Joshi static PredNode * 20712d16de5SRahul Joshi propagateGroundTruth(PredNode *node, 20812d16de5SRahul Joshi const llvm::SmallPtrSetImpl<Pred *> &knownTruePreds, 20912d16de5SRahul Joshi const llvm::SmallPtrSetImpl<Pred *> &knownFalsePreds) { 21005b02bb9SAlex Zinenko // If the current predicate is known to be true or false, change the kind of 21105b02bb9SAlex Zinenko // the node and return immediately. 21205b02bb9SAlex Zinenko if (knownTruePreds.count(node->predicate) != 0) { 21305b02bb9SAlex Zinenko node->kind = PredCombinerKind::True; 21405b02bb9SAlex Zinenko node->children.clear(); 21505b02bb9SAlex Zinenko return node; 21605b02bb9SAlex Zinenko } 21705b02bb9SAlex Zinenko if (knownFalsePreds.count(node->predicate) != 0) { 21805b02bb9SAlex Zinenko node->kind = PredCombinerKind::False; 21905b02bb9SAlex Zinenko node->children.clear(); 22005b02bb9SAlex Zinenko return node; 22105b02bb9SAlex Zinenko } 22205b02bb9SAlex Zinenko 22305b02bb9SAlex Zinenko // If the current node is a substitution, stop recursion now. 22405b02bb9SAlex Zinenko // The expressions in the leaves below this node were rewritten, but the nodes 22505b02bb9SAlex Zinenko // still point to the original predicate records. While the original 22605b02bb9SAlex Zinenko // predicate may be known to be true or false, it is not necessarily the case 22705b02bb9SAlex Zinenko // after rewriting. 2289db53a18SRiver Riddle // TODO: we can support ground truth for rewritten 22905b02bb9SAlex Zinenko // predicates by either (a) having our own unique'ing of the predicates 23005b02bb9SAlex Zinenko // instead of relying on TableGen record pointers or (b) taking ground truth 2318bfedb3cSKazuaki Ishizaki // values optionally prefixed with a list of substitutions to apply, e.g. 23205b02bb9SAlex Zinenko // "predX is true by itself as well as predSubY leaf substitution had been 23305b02bb9SAlex Zinenko // applied to it". 23405b02bb9SAlex Zinenko if (node->kind == PredCombinerKind::SubstLeaves) { 23505b02bb9SAlex Zinenko return node; 23605b02bb9SAlex Zinenko } 23705b02bb9SAlex Zinenko 238*d8399d5dSKrzysztof Drewniak if (node->kind == PredCombinerKind::And && node->children.empty()) { 239*d8399d5dSKrzysztof Drewniak node->kind = PredCombinerKind::True; 240*d8399d5dSKrzysztof Drewniak return node; 241*d8399d5dSKrzysztof Drewniak } 242*d8399d5dSKrzysztof Drewniak 243*d8399d5dSKrzysztof Drewniak if (node->kind == PredCombinerKind::Or && node->children.empty()) { 244*d8399d5dSKrzysztof Drewniak node->kind = PredCombinerKind::False; 245*d8399d5dSKrzysztof Drewniak return node; 246*d8399d5dSKrzysztof Drewniak } 247*d8399d5dSKrzysztof Drewniak 24805b02bb9SAlex Zinenko // Otherwise, look at child nodes. 24905b02bb9SAlex Zinenko 25005b02bb9SAlex Zinenko // Move child nodes into some local variable so that they can be optimized 25105b02bb9SAlex Zinenko // separately and re-added if necessary. 25205b02bb9SAlex Zinenko llvm::SmallVector<PredNode *, 4> children; 25305b02bb9SAlex Zinenko std::swap(node->children, children); 25405b02bb9SAlex Zinenko 25505b02bb9SAlex Zinenko for (auto &child : children) { 25605b02bb9SAlex Zinenko // First, simplify the child. This maintains the predicate as it was. 25702b6fb21SMehdi Amini auto *simplifiedChild = 25805b02bb9SAlex Zinenko propagateGroundTruth(child, knownTruePreds, knownFalsePreds); 25905b02bb9SAlex Zinenko 26005b02bb9SAlex Zinenko // Just add the child if we don't know how to simplify the current node. 26105b02bb9SAlex Zinenko if (node->kind != PredCombinerKind::And && 26205b02bb9SAlex Zinenko node->kind != PredCombinerKind::Or) { 26305b02bb9SAlex Zinenko node->children.push_back(simplifiedChild); 26405b02bb9SAlex Zinenko continue; 26505b02bb9SAlex Zinenko } 26605b02bb9SAlex Zinenko 26705b02bb9SAlex Zinenko // Second, based on the type define which known values of child predicates 26805b02bb9SAlex Zinenko // immediately collapse this predicate to a known value, and which others 26905b02bb9SAlex Zinenko // may be safely ignored. 27005b02bb9SAlex Zinenko // OR(..., True, ...) = True 27105b02bb9SAlex Zinenko // OR(..., False, ...) = OR(..., ...) 27205b02bb9SAlex Zinenko // AND(..., False, ...) = False 27305b02bb9SAlex Zinenko // AND(..., True, ...) = AND(..., ...) 27405b02bb9SAlex Zinenko auto collapseKind = node->kind == PredCombinerKind::And 27505b02bb9SAlex Zinenko ? PredCombinerKind::False 27605b02bb9SAlex Zinenko : PredCombinerKind::True; 27705b02bb9SAlex Zinenko auto eraseKind = node->kind == PredCombinerKind::And 27805b02bb9SAlex Zinenko ? PredCombinerKind::True 27905b02bb9SAlex Zinenko : PredCombinerKind::False; 28005b02bb9SAlex Zinenko const auto &collapseList = 28105b02bb9SAlex Zinenko node->kind == PredCombinerKind::And ? knownFalsePreds : knownTruePreds; 28205b02bb9SAlex Zinenko const auto &eraseList = 28305b02bb9SAlex Zinenko node->kind == PredCombinerKind::And ? knownTruePreds : knownFalsePreds; 28405b02bb9SAlex Zinenko if (simplifiedChild->kind == collapseKind || 28505b02bb9SAlex Zinenko collapseList.count(simplifiedChild->predicate) != 0) { 28605b02bb9SAlex Zinenko node->kind = collapseKind; 28705b02bb9SAlex Zinenko node->children.clear(); 28805b02bb9SAlex Zinenko return node; 28902b6fb21SMehdi Amini } 29002b6fb21SMehdi Amini if (simplifiedChild->kind == eraseKind || 29105b02bb9SAlex Zinenko eraseList.count(simplifiedChild->predicate) != 0) { 29205b02bb9SAlex Zinenko continue; 29305b02bb9SAlex Zinenko } 29405b02bb9SAlex Zinenko node->children.push_back(simplifiedChild); 29505b02bb9SAlex Zinenko } 29605b02bb9SAlex Zinenko return node; 29705b02bb9SAlex Zinenko } 29805b02bb9SAlex Zinenko 29905b02bb9SAlex Zinenko // Combine a list of predicate expressions using a binary combiner. If a list 30005b02bb9SAlex Zinenko // is empty, return "init". 30105b02bb9SAlex Zinenko static std::string combineBinary(ArrayRef<std::string> children, 3021fc096afSMehdi Amini const std::string &combiner, 3031fc096afSMehdi Amini std::string init) { 30405b02bb9SAlex Zinenko if (children.empty()) 30505b02bb9SAlex Zinenko return init; 30605b02bb9SAlex Zinenko 30705b02bb9SAlex Zinenko auto size = children.size(); 30805b02bb9SAlex Zinenko if (size == 1) 30905b02bb9SAlex Zinenko return children.front(); 31005b02bb9SAlex Zinenko 31105b02bb9SAlex Zinenko std::string str; 31205b02bb9SAlex Zinenko llvm::raw_string_ostream os(str); 31305b02bb9SAlex Zinenko os << '(' << children.front() << ')'; 31405b02bb9SAlex Zinenko for (unsigned i = 1; i < size; ++i) { 31505b02bb9SAlex Zinenko os << ' ' << combiner << " (" << children[i] << ')'; 31605b02bb9SAlex Zinenko } 317095b41c6SJOE1994 return str; 31805b02bb9SAlex Zinenko } 31905b02bb9SAlex Zinenko 32005b02bb9SAlex Zinenko // Prepend negation to the only condition in the predicate expression list. 32105b02bb9SAlex Zinenko static std::string combineNot(ArrayRef<std::string> children) { 32205b02bb9SAlex Zinenko assert(children.size() == 1 && "expected exactly one child predicate of Neg"); 32305b02bb9SAlex Zinenko return (Twine("!(") + children.front() + Twine(')')).str(); 32405b02bb9SAlex Zinenko } 32505b02bb9SAlex Zinenko 32605b02bb9SAlex Zinenko // Recursively traverse the predicate tree in depth-first post-order and build 32705b02bb9SAlex Zinenko // the final expression. 32805b02bb9SAlex Zinenko static std::string getCombinedCondition(const PredNode &root) { 32905b02bb9SAlex Zinenko // Immediately return for non-combiner predicates that don't have children. 33005b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::Leaf) 33105b02bb9SAlex Zinenko return root.expr; 33205b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::True) 33305b02bb9SAlex Zinenko return "true"; 33405b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::False) 33505b02bb9SAlex Zinenko return "false"; 33605b02bb9SAlex Zinenko 33705b02bb9SAlex Zinenko // Recurse into children. 33805b02bb9SAlex Zinenko llvm::SmallVector<std::string, 4> childExpressions; 33905b02bb9SAlex Zinenko childExpressions.reserve(root.children.size()); 34005b02bb9SAlex Zinenko for (const auto &child : root.children) 34105b02bb9SAlex Zinenko childExpressions.push_back(getCombinedCondition(*child)); 34205b02bb9SAlex Zinenko 34305b02bb9SAlex Zinenko // Combine the expressions based on the predicate node kind. 34405b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::And) 34505b02bb9SAlex Zinenko return combineBinary(childExpressions, "&&", "true"); 34605b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::Or) 34705b02bb9SAlex Zinenko return combineBinary(childExpressions, "||", "false"); 34805b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::Not) 34905b02bb9SAlex Zinenko return combineNot(childExpressions); 350b5235d1aSLei Zhang if (root.kind == PredCombinerKind::Concat) { 351b5235d1aSLei Zhang assert(childExpressions.size() == 1 && 352b5235d1aSLei Zhang "ConcatPred should only have one child"); 353b5235d1aSLei Zhang return root.prefix + childExpressions.front() + root.suffix; 354b5235d1aSLei Zhang } 35505b02bb9SAlex Zinenko 35605b02bb9SAlex Zinenko // Substitutions were applied before so just ignore them. 35705b02bb9SAlex Zinenko if (root.kind == PredCombinerKind::SubstLeaves) { 35805b02bb9SAlex Zinenko assert(childExpressions.size() == 1 && 35905b02bb9SAlex Zinenko "substitution predicate must have one child"); 36005b02bb9SAlex Zinenko return childExpressions[0]; 36105b02bb9SAlex Zinenko } 36205b02bb9SAlex Zinenko 36305b02bb9SAlex Zinenko llvm::PrintFatalError(root.predicate->getLoc(), "unsupported predicate kind"); 36405b02bb9SAlex Zinenko } 36505b02bb9SAlex Zinenko 36612d16de5SRahul Joshi std::string CombinedPred::getConditionImpl() const { 367659192b1SRahul Joshi SpecificBumpPtrAllocator<PredNode> allocator; 36802b6fb21SMehdi Amini auto *predicateTree = buildPredicateTree(*this, allocator, {}); 36912d16de5SRahul Joshi predicateTree = 37012d16de5SRahul Joshi propagateGroundTruth(predicateTree, 37112d16de5SRahul Joshi /*knownTruePreds=*/llvm::SmallPtrSet<Pred *, 2>(), 37212d16de5SRahul Joshi /*knownFalsePreds=*/llvm::SmallPtrSet<Pred *, 2>()); 37305b02bb9SAlex Zinenko 37405b02bb9SAlex Zinenko return getCombinedCondition(*predicateTree); 37505b02bb9SAlex Zinenko } 37605b02bb9SAlex Zinenko 37712d16de5SRahul Joshi StringRef SubstLeavesPred::getPattern() const { 37805b02bb9SAlex Zinenko return def->getValueAsString("pattern"); 37905b02bb9SAlex Zinenko } 38005b02bb9SAlex Zinenko 38112d16de5SRahul Joshi StringRef SubstLeavesPred::getReplacement() const { 38205b02bb9SAlex Zinenko return def->getValueAsString("replacement"); 38305b02bb9SAlex Zinenko } 384b5235d1aSLei Zhang 38512d16de5SRahul Joshi StringRef ConcatPred::getPrefix() const { 386b5235d1aSLei Zhang return def->getValueAsString("prefix"); 387b5235d1aSLei Zhang } 388b5235d1aSLei Zhang 38912d16de5SRahul Joshi StringRef ConcatPred::getSuffix() const { 390b5235d1aSLei Zhang return def->getValueAsString("suffix"); 391b5235d1aSLei Zhang } 392