Index: llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h @@ -132,6 +132,7 @@ OPC_CheckChild2Same, OPC_CheckChild3Same, OPC_CheckPatternPredicate, OPC_CheckPredicate, + OPC_CheckPredicateWithOperands, OPC_CheckOpcode, OPC_SwitchOpcode, OPC_CheckType, @@ -267,6 +268,17 @@ llvm_unreachable("Tblgen should generate the implementation of this!"); } + /// CheckNodePredicateWithOperands - This function is generated by tblgen in + /// the target. + /// It runs node predicate number PredNo and returns true if it succeeds or + /// false if it fails. The number is a private implementation detail to the + /// code tblgen produces. + virtual bool CheckNodePredicateWithOperands( + SDNode *N, unsigned PredNo, + const SmallVectorImpl &Operands) const { + llvm_unreachable("Tblgen should generate the implementation of this!"); + } + virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N, unsigned PatternNo, SmallVectorImpl > &Result) { Index: llvm/trunk/include/llvm/Target/TargetSelectionDAG.td =================================================================== --- llvm/trunk/include/llvm/Target/TargetSelectionDAG.td +++ llvm/trunk/include/llvm/Target/TargetSelectionDAG.td @@ -630,6 +630,15 @@ code ImmediateCode = [{}]; SDNodeXForm OperandTransform = xform; + // When this is set, the PredicateCode may refer to a constant Operands + // vector which contains the captured nodes of the DAG, in the order listed + // by the Operands field above. + // + // This is useful when Fragments involves associative / commutative + // operators: a single piece of code can easily refer to all operands even + // when re-associated / commuted variants of the fragment are matched. + bit PredicateCodeUsesOperands = 0; + // Define a few pre-packaged predicates. This helps GlobalISel import // existing rules from SelectionDAG for many common cases. // They will be tested prior to the code in pred and must not be used in Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -3207,6 +3207,18 @@ N.getNode())) break; continue; + case OPC_CheckPredicateWithOperands: { + unsigned OpNum = MatcherTable[MatcherIndex++]; + SmallVector Operands; + + for (unsigned i = 0; i < OpNum; ++i) + Operands.push_back(RecordedNodes[MatcherTable[MatcherIndex++]].first); + + unsigned PredNo = MatcherTable[MatcherIndex++]; + if (!CheckNodePredicateWithOperands(N.getNode(), PredNo, Operands)) + break; + continue; + } case OPC_CheckComplexPat: { unsigned CPNum = MatcherTable[MatcherIndex++]; unsigned RecNo = MatcherTable[MatcherIndex++]; Index: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h =================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h @@ -408,6 +408,29 @@ TreePattern &TP) const; }; +/// ScopedName - A name of a node associated with a "scope" that indicates +/// the context (e.g. instance of Pattern or PatFrag) in which the name was +/// used. This enables substitution of pattern fragments while keeping track +/// of what name(s) were originally given to various nodes in the tree. +class ScopedName { + unsigned Scope; + std::string Identifier; +public: + ScopedName(unsigned Scope, StringRef Identifier) + : Scope(Scope), Identifier(Identifier) { + assert(Scope != 0 && + "Scope == 0 is used to indicate predicates without arguments"); + } + + unsigned getScope() const { return Scope; } + const std::string &getIdentifier() const { return Identifier; } + + std::string getFullName() const; + + bool operator==(const ScopedName &o) const; + bool operator!=(const ScopedName &o) const; +}; + /// SDNodeInfo - One of these records is created for each SDNode instance in /// the target .td file. This represents the various dag nodes we will be /// processing. @@ -503,6 +526,9 @@ /// usable as part of an identifier. StringRef getImmTypeIdentifier() const; + // Predicate code uses the PatFrag's captured operands. + bool usesOperands() const; + // Is the desired predefined predicate for a load? bool isLoad() const; // Is the desired predefined predicate for a store? @@ -570,6 +596,23 @@ bool isPredefinedPredicateEqualTo(StringRef Field, bool Value) const; }; +struct TreePredicateCall { + TreePredicateFn Fn; + + // Scope -- unique identifier for retrieving named arguments. 0 is used when + // the predicate does not use named arguments. + unsigned Scope; + + TreePredicateCall(const TreePredicateFn &Fn, unsigned Scope) + : Fn(Fn), Scope(Scope) {} + + bool operator==(const TreePredicateCall &o) const { + return Fn == o.Fn && Scope == o.Scope; + } + bool operator!=(const TreePredicateCall &o) const { + return !(*this == o); + } +}; class TreePatternNode { /// The type of each node result. Before and during type inference, each @@ -589,9 +632,11 @@ /// std::string Name; - /// PredicateFns - The predicate functions to execute on this node to check + std::vector NamesAsPredicateArg; + + /// PredicateCalls - The predicate functions to execute on this node to check /// for a match. If this list is empty, no predicate is involved. - std::vector PredicateFns; + std::vector PredicateCalls; /// TransformFn - The transformation function to execute on this node before /// it can be substituted into the resulting instruction on a pattern match. @@ -615,6 +660,16 @@ const std::string &getName() const { return Name; } void setName(StringRef N) { Name.assign(N.begin(), N.end()); } + const std::vector &getNamesAsPredicateArg() const { + return NamesAsPredicateArg; + } + void setNamesAsPredicateArg(const std::vector& Names) { + NamesAsPredicateArg = Names; + } + void addNameAsPredicateArg(const ScopedName &N) { + NamesAsPredicateArg.push_back(N); + } + bool isLeaf() const { return Val != nullptr; } // Type accessors. @@ -661,20 +716,24 @@ bool hasPossibleType() const; bool setDefaultMode(unsigned Mode); - bool hasAnyPredicate() const { return !PredicateFns.empty(); } + bool hasAnyPredicate() const { return !PredicateCalls.empty(); } - const std::vector &getPredicateFns() const { - return PredicateFns; + const std::vector &getPredicateCalls() const { + return PredicateCalls; } - void clearPredicateFns() { PredicateFns.clear(); } - void setPredicateFns(const std::vector &Fns) { - assert(PredicateFns.empty() && "Overwriting non-empty predicate list!"); - PredicateFns = Fns; - } - void addPredicateFn(const TreePredicateFn &Fn) { - assert(!Fn.isAlwaysTrue() && "Empty predicate string!"); - assert(!is_contained(PredicateFns, Fn) && "predicate applied recursively"); - PredicateFns.push_back(Fn); + void clearPredicateCalls() { PredicateCalls.clear(); } + void setPredicateCalls(const std::vector &Calls) { + assert(PredicateCalls.empty() && "Overwriting non-empty predicate list!"); + PredicateCalls = Calls; + } + void addPredicateCall(const TreePredicateCall &Call) { + assert(!Call.Fn.isAlwaysTrue() && "Empty predicate string!"); + assert(!is_contained(PredicateCalls, Call) && "predicate applied recursively"); + PredicateCalls.push_back(Call); + } + void addPredicateCall(const TreePredicateFn &Fn, unsigned Scope) { + assert((Scope != 0) == Fn.usesOperands()); + addPredicateCall(TreePredicateCall(Fn, Scope)); } Record *getTransformFn() const { return TransformFn; } @@ -1081,6 +1140,8 @@ using PatternRewriterFn = std::function; PatternRewriterFn PatternRewriter; + unsigned NumScopes = 0; + public: CodeGenDAGPatterns(RecordKeeper &R, PatternRewriterFn PatternRewriter = nullptr); @@ -1196,6 +1257,8 @@ bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); } + unsigned allocateScope() { return ++NumScopes; } + private: void ParseNodeInfo(); void ParseNodeTransforms(); Index: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp =================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp @@ -824,6 +824,20 @@ } #endif + +//===----------------------------------------------------------------------===// +// ScopedName Implementation +//===----------------------------------------------------------------------===// + +bool ScopedName::operator==(const ScopedName &o) const { + return Scope == o.Scope && Identifier == o.Identifier; +} + +bool ScopedName::operator!=(const ScopedName &o) const { + return !(*this == o); +} + + //===----------------------------------------------------------------------===// // TreePredicateFn Implementation //===----------------------------------------------------------------------===// @@ -1069,6 +1083,9 @@ return false; return Result == Value; } +bool TreePredicateFn::usesOperands() const { + return isPredefinedPredicateEqualTo("PredicateCodeUsesOperands", true); +} bool TreePredicateFn::isLoad() const { return isPredefinedPredicateEqualTo("IsLoad", true); } @@ -1250,7 +1267,7 @@ else Result = " auto *N = cast<" + ClassName.str() + ">(Node);\n"; - return Result + getPredCode(); + return (Twine(Result) + " (void)N;\n" + getPredCode()).str(); } //===----------------------------------------------------------------------===// @@ -1276,7 +1293,7 @@ // If this node has some predicate function that must match, it adds to the // complexity of this node. - if (!P->getPredicateFns().empty()) + if (!P->getPredicateCalls().empty()) ++Size; // Count children in the count if they are also nodes. @@ -1296,7 +1313,7 @@ Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). else if (Child->getComplexPatternInfo(CGP)) Size += getPatternSize(Child, CGP); - else if (!Child->getPredicateFns().empty()) + else if (!Child->getPredicateCalls().empty()) ++Size; } } @@ -1751,13 +1768,19 @@ OS << ")"; } - for (const TreePredicateFn &Pred : PredicateFns) - OS << "<>"; + for (const TreePredicateCall &Pred : PredicateCalls) { + OS << "<>"; + } if (TransformFn) OS << "<getName() << ">>"; if (!getName().empty()) OS << ":$" << getName(); + for (const ScopedName &Name : NamesAsPredicateArg) + OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier(); } void TreePatternNode::dump() const { print(errs()); @@ -1774,7 +1797,7 @@ const MultipleUseVarSet &DepVars) const { if (N == this) return true; if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() || - getPredicateFns() != N->getPredicateFns() || + getPredicateCalls() != N->getPredicateCalls() || getTransformFn() != N->getTransformFn()) return false; @@ -1812,8 +1835,9 @@ getNumTypes()); } New->setName(getName()); + New->setNamesAsPredicateArg(getNamesAsPredicateArg()); New->Types = Types; - New->setPredicateFns(getPredicateFns()); + New->setPredicateCalls(getPredicateCalls()); New->setTransformFn(getTransformFn()); return New; } @@ -1845,8 +1869,8 @@ // We found a use of a formal argument, replace it with its value. TreePatternNodePtr NewChild = ArgMap[Child->getName()]; assert(NewChild && "Couldn't find formal argument!"); - assert((Child->getPredicateFns().empty() || - NewChild->getPredicateFns() == Child->getPredicateFns()) && + assert((Child->getPredicateCalls().empty() || + NewChild->getPredicateCalls() == Child->getPredicateCalls()) && "Non-empty child predicate clobbered!"); setChild(i, std::move(NewChild)); } @@ -1892,8 +1916,8 @@ return; for (auto NewChild : ChildAlternatives[i]) - assert((Child->getPredicateFns().empty() || - NewChild->getPredicateFns() == Child->getPredicateFns()) && + assert((Child->getPredicateCalls().empty() || + NewChild->getPredicateCalls() == Child->getPredicateCalls()) && "Non-empty child predicate clobbered!"); } @@ -1911,7 +1935,8 @@ // Copy over properties. R->setName(getName()); - R->setPredicateFns(getPredicateFns()); + R->setNamesAsPredicateArg(getNamesAsPredicateArg()); + R->setPredicateCalls(getPredicateCalls()); R->setTransformFn(getTransformFn()); for (unsigned i = 0, e = getNumTypes(); i != e; ++i) R->setType(i, getExtType(i)); @@ -1946,10 +1971,19 @@ return; } + TreePredicateFn PredFn(Frag); + unsigned Scope = 0; + if (TreePredicateFn(Frag).usesOperands()) + Scope = TP.getDAGPatterns().allocateScope(); + // Compute the map of formal to actual arguments. std::map ArgMap; for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) { - const TreePatternNodePtr &Child = getChildShared(i); + TreePatternNodePtr Child = getChildShared(i); + if (Scope != 0) { + Child = Child->clone(); + Child->addNameAsPredicateArg(ScopedName(Scope, Frag->getArgName(i))); + } ArgMap[Frag->getArgName(i)] = Child; } @@ -1957,9 +1991,8 @@ for (auto Alternative : Frag->getTrees()) { TreePatternNodePtr FragTree = Alternative->clone(); - TreePredicateFn PredFn(Frag); if (!PredFn.isAlwaysTrue()) - FragTree->addPredicateFn(PredFn); + FragTree->addPredicateCall(PredFn, Scope); // Resolve formal arguments to their actual value. if (Frag->getNumArgs()) @@ -1972,8 +2005,8 @@ FragTree->UpdateNodeType(i, getExtType(i), TP); // Transfer in the old predicates. - for (const TreePredicateFn &Pred : getPredicateFns()) - FragTree->addPredicateFn(Pred); + for (const TreePredicateCall &Pred : getPredicateCalls()) + FragTree->addPredicateCall(Pred); // The fragment we inlined could have recursive inlining that is needed. See // if there are any pattern fragments in it and inline them as needed. @@ -3596,7 +3629,7 @@ TreePatternNodePtr OpNode = InVal->clone(); // No predicate is useful on the result. - OpNode->clearPredicateFns(); + OpNode->clearPredicateCalls(); // Promote the xform function to be an explicit node if set. if (Record *Xform = OpNode->getTransformFn()) { @@ -4251,7 +4284,8 @@ // Copy over properties. R->setName(Orig->getName()); - R->setPredicateFns(Orig->getPredicateFns()); + R->setNamesAsPredicateArg(Orig->getNamesAsPredicateArg()); + R->setPredicateCalls(Orig->getPredicateCalls()); R->setTransformFn(Orig->getTransformFn()); for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) R->setType(i, Orig->getExtType(i)); @@ -4303,7 +4337,7 @@ Record *Operator = N->getOperator(); // Only permit raw nodes. - if (!N->getName().empty() || !N->getPredicateFns().empty() || + if (!N->getName().empty() || !N->getPredicateCalls().empty() || N->getTransformFn()) { Children.push_back(N); return; Index: llvm/trunk/utils/TableGen/DAGISelMatcher.h =================================================================== --- llvm/trunk/utils/TableGen/DAGISelMatcher.h +++ llvm/trunk/utils/TableGen/DAGISelMatcher.h @@ -414,10 +414,14 @@ /// see if the node is acceptable. class CheckPredicateMatcher : public Matcher { TreePattern *Pred; + const SmallVector Operands; public: - CheckPredicateMatcher(const TreePredicateFn &pred); + CheckPredicateMatcher(const TreePredicateFn &pred, + const SmallVectorImpl &Operands); TreePredicateFn getPredicate() const; + unsigned getNumOperands() const; + unsigned getOperandNo(unsigned i) const; static bool classof(const Matcher *N) { return N->getKind() == CheckPredicate; Index: llvm/trunk/utils/TableGen/DAGISelMatcher.cpp =================================================================== --- llvm/trunk/utils/TableGen/DAGISelMatcher.cpp +++ llvm/trunk/utils/TableGen/DAGISelMatcher.cpp @@ -93,13 +93,23 @@ delete C.second; } -CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred) - : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {} +CheckPredicateMatcher::CheckPredicateMatcher( + const TreePredicateFn &pred, const SmallVectorImpl &Ops) + : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()), + Operands(Ops.begin(), Ops.end()) {} TreePredicateFn CheckPredicateMatcher::getPredicate() const { return TreePredicateFn(Pred); } +unsigned CheckPredicateMatcher::getNumOperands() const { + return Operands.size(); +} + +unsigned CheckPredicateMatcher::getOperandNo(unsigned i) const { + assert(i < Operands.size()); + return Operands[i]; +} // printImpl methods. Index: llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp +++ llvm/trunk/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -50,6 +50,7 @@ DenseMap NodePredicateMap; std::vector NodePredicates; + std::vector NodePredicatesWithOperands; // We de-duplicate the predicates by code string, and use this map to track // all the patterns with "identical" predicates. @@ -92,6 +93,9 @@ void EmitPatternMatchTable(raw_ostream &OS); private: + void EmitNodePredicatesFunction(const std::vector &Preds, + StringRef Decl, raw_ostream &OS); + unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, raw_ostream &OS); @@ -103,12 +107,20 @@ NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()]; if (SameCodePreds.empty()) { // We've never seen a predicate with the same code: allocate an entry. - NodePredicates.push_back(Pred); - Entry = NodePredicates.size(); + if (Pred.usesOperands()) { + NodePredicatesWithOperands.push_back(Pred); + Entry = NodePredicatesWithOperands.size(); + } else { + NodePredicates.push_back(Pred); + Entry = NodePredicates.size(); + } } else { // We did see an identical predicate: re-use it. Entry = NodePredicateMap[SameCodePreds.front()]; assert(Entry != 0); + assert(TreePredicateFn(SameCodePreds.front()).usesOperands() == + Pred.usesOperands() && + "PatFrags with some code must have same usesOperands setting"); } // In both cases, we've never seen this particular predicate before, so // mark it in the list of predicates sharing the same code. @@ -396,11 +408,23 @@ } case Matcher::CheckPredicate: { TreePredicateFn Pred = cast(N)->getPredicate(); - OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ','; + unsigned OperandBytes = 0; + + if (Pred.usesOperands()) { + unsigned NumOps = cast(N)->getNumOperands(); + OS << "OPC_CheckPredicateWithOperands, " << NumOps << "/*#Ops*/, "; + for (unsigned i = 0; i < NumOps; ++i) + OS << cast(N)->getOperandNo(i) << ", "; + OperandBytes = 1 + NumOps; + } else { + OS << "OPC_CheckPredicate, "; + } + + OS << getNodePredicate(Pred) << ','; if (!OmitComments) OS << " // " << Pred.getFnName(); OS << '\n'; - return 2; + return 2 + OperandBytes; } case Matcher::CheckOpcode: @@ -783,6 +807,33 @@ return Size; } +void MatcherTableEmitter::EmitNodePredicatesFunction( + const std::vector &Preds, StringRef Decl, + raw_ostream &OS) { + if (Preds.empty()) + return; + + BeginEmitFunction(OS, "bool", Decl, true/*AddOverride*/); + OS << "{\n"; + OS << " switch (PredNo) {\n"; + OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + // Emit the predicate code corresponding to this pattern. + TreePredicateFn PredFn = Preds[i]; + + assert(!PredFn.isAlwaysTrue() && "No code in this predicate"); + OS << " case " << i << ": { \n"; + for (auto *SimilarPred : + NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()]) + OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n'; + + OS << PredFn.getCodeToRunOnSDNode() << "\n }\n"; + } + OS << " }\n"; + OS << "}\n"; + EndEmitFunction(OS); +} + void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) { // Emit pattern predicates. if (!PatternPredicates.empty()) { @@ -799,29 +850,14 @@ } // Emit Node predicates. - if (!NodePredicates.empty()) { - BeginEmitFunction(OS, "bool", - "CheckNodePredicate(SDNode *Node, unsigned PredNo) const", - true/*AddOverride*/); - OS << "{\n"; - OS << " switch (PredNo) {\n"; - OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; - for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) { - // Emit the predicate code corresponding to this pattern. - TreePredicateFn PredFn = NodePredicates[i]; - - assert(!PredFn.isAlwaysTrue() && "No code in this predicate"); - OS << " case " << i << ": { \n"; - for (auto *SimilarPred : - NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()]) - OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n'; - - OS << PredFn.getCodeToRunOnSDNode() << "\n }\n"; - } - OS << " }\n"; - OS << "}\n"; - EndEmitFunction(OS); - } + EmitNodePredicatesFunction( + NodePredicates, "CheckNodePredicate(SDNode *Node, unsigned PredNo) const", + OS); + EmitNodePredicatesFunction( + NodePredicatesWithOperands, + "CheckNodePredicateWithOperands(SDNode *Node, unsigned PredNo, " + "const SmallVectorImpl &Operands) const", + OS); // Emit CompletePattern matchers. // FIXME: This should be const. Index: llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp =================================================================== --- llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp +++ llvm/trunk/utils/TableGen/DAGISelMatcherGen.cpp @@ -120,7 +120,7 @@ /// If this is the first time a node with unique identifier Name has been /// seen, record it. Otherwise, emit a check to make sure this is the same /// node. Returns true if this is the first encounter. - bool recordUniqueNode(const std::string &Name); + bool recordUniqueNode(ArrayRef Names); // Result Code Generation. unsigned getNamedArgumentSlot(StringRef Name) { @@ -319,8 +319,8 @@ // to handle this. if ((N->getOperator()->getName() == "and" || N->getOperator()->getName() == "or") && - N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() && - N->getPredicateFns().empty()) { + N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateCalls().empty() && + N->getPredicateCalls().empty()) { if (IntInit *II = dyn_cast(N->getChild(1)->getLeafValue())) { if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits. // If this is at the root of the pattern, we emit a redundant @@ -441,21 +441,39 @@ } } -bool MatcherGen::recordUniqueNode(const std::string &Name) { - unsigned &VarMapEntry = VariableMap[Name]; - if (VarMapEntry == 0) { +bool MatcherGen::recordUniqueNode(ArrayRef Names) { + unsigned Entry = 0; + for (const std::string &Name : Names) { + unsigned &VarMapEntry = VariableMap[Name]; + if (!Entry) + Entry = VarMapEntry; + assert(Entry == VarMapEntry); + } + + bool NewRecord = false; + if (Entry == 0) { // If it is a named node, we must emit a 'Record' opcode. - AddMatcher(new RecordMatcher("$" + Name, NextRecordedOperandNo)); - VarMapEntry = ++NextRecordedOperandNo; - return true; + std::string WhatFor; + for (const std::string &Name : Names) { + if (!WhatFor.empty()) + WhatFor += ','; + WhatFor += "$" + Name; + } + AddMatcher(new RecordMatcher(WhatFor, NextRecordedOperandNo)); + Entry = ++NextRecordedOperandNo; + NewRecord = true; + } else { + // If we get here, this is a second reference to a specific name. Since + // we already have checked that the first reference is valid, we don't + // have to recursively match it, just check that it's the same as the + // previously named thing. + AddMatcher(new CheckSameMatcher(Entry-1)); } - // If we get here, this is a second reference to a specific name. Since - // we already have checked that the first reference is valid, we don't - // have to recursively match it, just check that it's the same as the - // previously named thing. - AddMatcher(new CheckSameMatcher(VarMapEntry-1)); - return false; + for (const std::string &Name : Names) + VariableMap[Name] = Entry; + + return NewRecord; } void MatcherGen::EmitMatchCode(const TreePatternNode *N, @@ -475,9 +493,18 @@ // If this node has a name associated with it, capture it in VariableMap. If // we already saw this in the pattern, emit code to verify dagness. + SmallVector Names; if (!N->getName().empty()) - if (!recordUniqueNode(N->getName())) + Names.push_back(N->getName()); + + for (const ScopedName &Name : N->getNamesAsPredicateArg()) { + Names.push_back(("pred:" + Twine(Name.getScope()) + ":" + Name.getIdentifier()).str()); + } + + if (!Names.empty()) { + if (!recordUniqueNode(Names)) return; + } if (N->isLeaf()) EmitLeafMatchCode(N); @@ -485,8 +512,19 @@ EmitOperatorMatchCode(N, NodeNoTypes, ForceMode); // If there are node predicates for this node, generate their checks. - for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) - AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i])); + for (unsigned i = 0, e = N->getPredicateCalls().size(); i != e; ++i) { + const TreePredicateCall &Pred = N->getPredicateCalls()[i]; + SmallVector Operands; + if (Pred.Fn.usesOperands()) { + TreePattern *TP = Pred.Fn.getOrigPatFragRecord(); + for (unsigned i = 0; i < TP->getNumArgs(); ++i) { + std::string Name = + ("pred:" + Twine(Pred.Scope) + ":" + TP->getArgName(i)).str(); + Operands.push_back(getNamedArgumentSlot(Name)); + } + } + AddMatcher(new CheckPredicateMatcher(Pred.Fn, Operands)); + } for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i) AddMatcher(new CheckTypeMatcher(N->getSimpleType(ResultsToTypeCheck[i]), Index: llvm/trunk/utils/TableGen/FastISelEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/FastISelEmitter.cpp +++ llvm/trunk/utils/TableGen/FastISelEmitter.cpp @@ -210,13 +210,13 @@ // Handle imm operands specially. if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") { unsigned PredNo = 0; - if (!Op->getPredicateFns().empty()) { - TreePredicateFn PredFn = Op->getPredicateFns()[0]; + if (!Op->getPredicateCalls().empty()) { + TreePredicateFn PredFn = Op->getPredicateCalls()[0].Fn; // If there is more than one predicate weighing in on this operand // then we don't handle it. This doesn't typically happen for // immediates anyway. - if (Op->getPredicateFns().size() > 1 || - !PredFn.isImmediatePattern()) + if (Op->getPredicateCalls().size() > 1 || + !PredFn.isImmediatePattern() || PredFn.usesOperands()) return false; // Ignore any instruction with 'FastIselShouldIgnore', these are // not needed and just bloat the fast instruction selector. For @@ -236,7 +236,7 @@ // For now, filter out any operand with a predicate. // For now, filter out any operand with multiple values. - if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1) + if (!Op->getPredicateCalls().empty() || Op->getNumTypes() != 1) return false; if (!Op->isLeaf()) { @@ -529,7 +529,7 @@ } // For now, filter out any instructions with predicates. - if (!InstPatNode->getPredicateFns().empty()) + if (!InstPatNode->getPredicateCalls().empty()) continue; // Check all the operands. Index: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp +++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp @@ -200,7 +200,8 @@ static std::string explainPredicates(const TreePatternNode *N) { std::string Explanation = ""; StringRef Separator = ""; - for (const auto &P : N->getPredicateFns()) { + for (const TreePredicateCall &Call : N->getPredicateCalls()) { + const TreePredicateFn &P = Call.Fn; Explanation += (Separator + P.getOrigPatFragRecord()->getRecord()->getName()).str(); Separator = ", "; @@ -284,7 +285,9 @@ std::string Separator = ""; bool HasUnsupportedPredicate = false; - for (const auto &Predicate : N->getPredicateFns()) { + for (const TreePredicateCall &Call : N->getPredicateCalls()) { + const TreePredicateFn &Predicate = Call.Fn; + if (Predicate.isAlwaysTrue()) continue; @@ -3117,7 +3120,8 @@ const CodeGenInstruction * GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode *N) const { - for (const auto &Predicate : N->getPredicateFns()) { + for (const TreePredicateCall &Call : N->getPredicateCalls()) { + const TreePredicateFn &Predicate = Call.Fn; if (!Equiv.isValueUnset("IfSignExtend") && Predicate.isLoad() && Predicate.isSignExtLoad()) return &Target.getInstruction(Equiv.getValueAsDef("IfSignExtend")); @@ -3186,7 +3190,8 @@ " for result of Src pattern operator"); } - for (const auto &Predicate : Src->getPredicateFns()) { + for (const TreePredicateCall &Call : Src->getPredicateCalls()) { + const TreePredicateFn &Predicate = Call.Fn; if (Predicate.isAlwaysTrue()) continue;