diff options
Diffstat (limited to 'utils/TableGen/DAGISelMatcherGen.cpp')
-rw-r--r-- | utils/TableGen/DAGISelMatcherGen.cpp | 102 |
1 files changed, 68 insertions, 34 deletions
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 4482803..5488853 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -72,6 +72,14 @@ namespace { /// nodes array of all of the recorded input nodes that have flag results. SmallVector<unsigned, 2> MatchedFlagResultNodes; + /// MatchedComplexPatterns - This maintains a list of all of the + /// ComplexPatterns that we need to check. The patterns are known to have + /// names which were recorded. The second element of each pair is the first + /// slot number that the OPC_CheckComplexPat opcode drops the matched + /// results into. + SmallVector<std::pair<const TreePatternNode*, + unsigned>, 2> MatchedComplexPatterns; + /// PhysRegInputs - List list has an entry for each explicitly specified /// physreg input to the pattern. The first elt is the Register node, the /// second is the recorded slot number the input pattern match saved it in. @@ -247,30 +255,9 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { exit(1); } - // Handle complex pattern. - const ComplexPattern &CP = CGP.getComplexPattern(LeafRec); - - // Emit a CheckComplexPat operation, which does the match (aborting if it - // fails) and pushes the matched operands onto the recorded nodes list. - AddMatcher(new CheckComplexPatMatcher(CP)); - - // Record the right number of operands. - NextRecordedOperandNo += CP.getNumOperands(); - if (CP.hasProperty(SDNPHasChain)) - ++NextRecordedOperandNo; // Chained node operand. - - // If the complex pattern has a chain, then we need to keep track of the - // fact that we just recorded a chain input. The chain input will be - // matched as the last operand of the predicate if it was successful. - if (CP.hasProperty(SDNPHasChain)) { - // It is the last operand recorded. - assert(NextRecordedOperandNo > 1 && - "Should have recorded input/result chains at least!"); - MatchedChainNodes.push_back(NextRecordedOperandNo-1); - } - - // TODO: Complex patterns can't have output flags, if they did, we'd want - // to record them. + // Remember this ComplexPattern so that we can emit it after all the other + // structural matches are done. + MatchedComplexPatterns.push_back(std::make_pair(N, 0)); return; } @@ -484,17 +471,56 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { if (Variant != 0) return true; } + // Emit the matcher for the pattern structure and types. + EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes); + // If the pattern has a predicate on it (e.g. only enabled when a subtarget // feature is around, do the check). - // FIXME: This should get emitted after the match code below to encourage - // sharing. This can't happen until we get an X86ISD::AddrMode node made by - // dag combine, eliminating the horrible side-effect-full stuff from - // X86's MatchAddress. if (!Pattern.getPredicateCheck().empty()) AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck())); - - // Emit the matcher for the pattern structure and types. - EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes); + + // Now that we've completed the structural type match, emit any ComplexPattern + // checks (e.g. addrmode matches). We emit this after the structural match + // because they are generally more expensive to evaluate and more difficult to + // factor. + for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) { + const TreePatternNode *N = MatchedComplexPatterns[i].first; + + // Remember where the results of this match get stuck. + MatchedComplexPatterns[i].second = NextRecordedOperandNo; + + // Get the slot we recorded the value in from the name on the node. + unsigned RecNodeEntry = VariableMap[N->getName()]; + assert(!N->getName().empty() && RecNodeEntry && + "Complex pattern should have a name and slot"); + --RecNodeEntry; // Entries in VariableMap are biased. + + const ComplexPattern &CP = + CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef()); + + // Emit a CheckComplexPat operation, which does the match (aborting if it + // fails) and pushes the matched operands onto the recorded nodes list. + AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry, + N->getName(), NextRecordedOperandNo)); + + // Record the right number of operands. + NextRecordedOperandNo += CP.getNumOperands(); + if (CP.hasProperty(SDNPHasChain)) { + // If the complex pattern has a chain, then we need to keep track of the + // fact that we just recorded a chain input. The chain input will be + // matched as the last operand of the predicate if it was successful. + ++NextRecordedOperandNo; // Chained node operand. + + // It is the last operand recorded. + assert(NextRecordedOperandNo > 1 && + "Should have recorded input/result chains at least!"); + MatchedChainNodes.push_back(NextRecordedOperandNo-1); + } + + // TODO: Complex patterns can't have output flags, if they did, we'd want + // to record them. + } + return false; } @@ -507,18 +533,26 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps){ assert(!N->getName().empty() && "Operand not named!"); - unsigned SlotNo = getNamedArgumentSlot(N->getName()); - // A reference to a complex pattern gets all of the results of the complex // pattern's match. if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { + unsigned SlotNo = 0; + for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) + if (MatchedComplexPatterns[i].first->getName() == N->getName()) { + SlotNo = MatchedComplexPatterns[i].second; + break; + } + assert(SlotNo != 0 && "Didn't get a slot number assigned?"); + // The first slot entry is the node itself, the subsequent entries are the // matched values. for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) - ResultOps.push_back(SlotNo+i+1); + ResultOps.push_back(SlotNo+i); return; } + unsigned SlotNo = getNamedArgumentSlot(N->getName()); + // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target // version of the immediate so that it doesn't get selected due to some other // node use. |