From eb66921adb943ea841e72c8eee4777607c48b70e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 1 Mar 2010 06:59:22 +0000 Subject: add a new OPC_SwitchOpcode which is semantically equivalent to a scope where every child starts with a CheckOpcode, but executes more efficiently. Enhance DAGISelMatcherOpt to form it. This also fixes a bug in CheckOpcode: apparently the SDNodeInfo objects are not pointer comparable, we have to compare the enum name. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97438 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/DAGISelMatcherOpt.cpp | 54 ++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'utils/TableGen/DAGISelMatcherOpt.cpp') diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 5fe21f6..41ce6ae 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -15,6 +15,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include @@ -152,7 +153,8 @@ static void ContractNodes(OwningPtr &MatcherPtr, // like X86 where many operations are valid on multiple types. if ((isa(N) || isa(N) || isa(N)) && - isa(N->getNext())) { + (isa(N->getNext()) || + isa(N->getNext()))) { // Unlink the two nodes from the list. Matcher *CheckType = MatcherPtr.take(); Matcher *CheckOpcode = CheckType->takeNext(); @@ -256,7 +258,7 @@ static void FactorNodes(OwningPtr &MatcherPtr) { } SmallVector NewOptionsToMatch; - + // Loop over options to match, merging neighboring patterns with identical // starting nodes into a shared matcher. for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) { @@ -342,13 +344,55 @@ static void FactorNodes(OwningPtr &MatcherPtr) { NewOptionsToMatch.push_back(Shared); } + + // If we're down to a single pattern to match, then we don't need this scope + // anymore. + if (NewOptionsToMatch.size() == 1) { + MatcherPtr.reset(NewOptionsToMatch[0]); + return; + } + + // If our factoring failed (didn't achieve anything) see if we can simplify in + // other ways. + + // Check to see if all of the leading entries are now opcode checks. If so, + // we can convert this Scope to be a OpcodeSwitch instead. + bool AllOpcodeChecks = true; + for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { + if (isa(NewOptionsToMatch[i])) continue; + +#if 0 + if (i > 3) { + errs() << "FAILING OPC #" << i << "\n"; + NewOptionsToMatch[i]->dump(); + } +#endif + + AllOpcodeChecks = false; + break; + } + + // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot. + if (AllOpcodeChecks) { + StringSet<> Opcodes; + SmallVector, 8> Cases; + for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { + CheckOpcodeMatcher *COM =cast(NewOptionsToMatch[i]); + assert(Opcodes.insert(COM->getOpcode().getEnumName()) && + "Duplicate opcodes not factored?"); + Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); + } + + MatcherPtr.reset(new SwitchOpcodeMatcher(&Cases[0], Cases.size())); + return; + } + // Reassemble a new Scope node. - assert(!NewOptionsToMatch.empty() && "where'd all our children go?"); + assert(!NewOptionsToMatch.empty() && + "Where'd all our children go? Did we really factor everything??"); if (NewOptionsToMatch.empty()) MatcherPtr.reset(0); - if (NewOptionsToMatch.size() == 1) - MatcherPtr.reset(NewOptionsToMatch[0]); else { Scope->setNumChildren(NewOptionsToMatch.size()); for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) -- cgit v1.1