diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 8 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcher.cpp | 55 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcher.h | 44 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherGen.cpp | 14 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherOpt.cpp | 132 | ||||
-rw-r--r-- | utils/lit/lit/TestRunner.py | 18 | ||||
-rw-r--r-- | utils/lit/lit/TestingConfig.py | 8 | ||||
-rw-r--r-- | utils/unittest/UnitTestMain/Makefile | 6 | ||||
-rw-r--r-- | utils/unittest/googletest/Makefile | 10 |
9 files changed, 233 insertions, 62 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index ce737bf..e793333 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1238,6 +1238,14 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { std::vector<std::pair<Init*, std::string> >())); return ParseTreePattern(Dag); } + + // Input argument? + if (R->getName() == "node") { + if (Dag->getArgName(0).empty()) + error("'node' argument requires a name to match with operand list"); + Args.push_back(Dag->getArgName(0)); + } + New = new TreePatternNode(DI); } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { New = ParseTreePattern(DI); diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index c4f1cbf..22d2fe8 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -29,6 +29,54 @@ void Matcher::printOne(raw_ostream &OS) const { printImpl(OS, 0); } +/// unlinkNode - Unlink the specified node from this chain. If Other == this, +/// we unlink the next pointer and return it. Otherwise we unlink Other from +/// the list and return this. +Matcher *Matcher::unlinkNode(Matcher *Other) { + if (this == Other) + return takeNext(); + + // Scan until we find the predecessor of Other. + Matcher *Cur = this; + for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext()) + /*empty*/; + + if (Cur == 0) return 0; + Cur->takeNext(); + Cur->setNext(Other->takeNext()); + return this; +} + +/// canMoveBefore - Return true if this matcher is the same as Other, or if +/// we can move this matcher past all of the nodes in-between Other and this +/// node. Other must be equal to or before this. +bool Matcher::canMoveBefore(const Matcher *Other) const { + for (;; Other = Other->getNext()) { + assert(Other && "Other didn't come before 'this'?"); + if (this == Other) return true; + + // We have to be able to move this node across the Other node. + if (!canMoveBeforeNode(Other)) + return false; + } +} + +/// canMoveBefore - Return true if it is safe to move the current matcher +/// across the specified one. +bool Matcher::canMoveBeforeNode(const Matcher *Other) const { + // We can move simple predicates before record nodes. + if (isSimplePredicateNode()) + return Other->isSimplePredicateOrRecordNode(); + + // We can move record nodes across simple predicates. + if (isSimplePredicateOrRecordNode()) + return isSimplePredicateNode(); + + // We can't move record nodes across each other etc. + return false; +} + + ScopeMatcher::~ScopeMatcher() { for (unsigned i = 0, e = Children.size(); i != e; ++i) delete Children[i]; @@ -345,3 +393,10 @@ bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const { return CIM->getValue() != getValue(); return false; } + +bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M)) + return CVT->getTypeName() != getTypeName(); + return false; +} + diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 7955c7e..ef7ecf4 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -113,6 +113,49 @@ public: return false; } + /// isSimplePredicateNode - Return true if this is a simple predicate that + /// operates on the node or its children without potential side effects or a + /// change of the current node. + bool isSimplePredicateNode() const { + switch (getKind()) { + default: return false; + case CheckSame: + case CheckPatternPredicate: + case CheckPredicate: + case CheckOpcode: + case CheckType: + case CheckChildType: + case CheckInteger: + case CheckCondCode: + case CheckValueType: + case CheckAndImm: + case CheckOrImm: + case CheckFoldableChainNode: + return true; + } + } + + /// isSimplePredicateOrRecordNode - Return true if this is a record node or + /// a simple predicate. + bool isSimplePredicateOrRecordNode() const { + return isSimplePredicateNode() || + getKind() == RecordNode || getKind() == RecordChild; + } + + /// unlinkNode - Unlink the specified node from this chain. If Other == this, + /// we unlink the next pointer and return it. Otherwise we unlink Other from + /// the list and return this. + Matcher *unlinkNode(Matcher *Other); + + /// canMoveBefore - Return true if this matcher is the same as Other, or if + /// we can move this matcher past all of the nodes in-between Other and this + /// node. Other must be equal to or before this. + bool canMoveBefore(const Matcher *Other) const; + + /// canMoveBefore - Return true if it is safe to move the current matcher + /// across the specified one. + bool canMoveBeforeNode(const Matcher *Other) const; + /// isContradictory - Return true of these two matchers could never match on /// the same node. bool isContradictory(const Matcher *Other) const { @@ -601,6 +644,7 @@ private: return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName; } virtual unsigned getHashImpl() const; + bool isContradictoryImpl(const Matcher *M) const; }; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 5488853..4951a42 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -201,10 +201,6 @@ void MatcherGen::AddMatcher(Matcher *NewNode) { void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { assert(N->isLeaf() && "Not a leaf?"); - // 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])); - // Direct match against an integer constant. if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { // If this is the root of the dag we're matching, we emit a redundant opcode @@ -310,11 +306,6 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // Check that the current opcode lines up. AddMatcher(new CheckOpcodeMatcher(CInfo)); - // 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])); - - // If this node has memory references (i.e. is a load or store), tell the // interpreter to capture them in the memref array. if (N->NodeHasProperty(SDNPMemOperand, CGP)) @@ -447,9 +438,12 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, else EmitOperatorMatchCode(N, NodeNoTypes); + // 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])); + if (NodeType != EEVT::isUnknown) AddMatcher(new CheckTypeMatcher((MVT::SimpleValueType)NodeType)); - } /// EmitMatcherCode - Generate the code that matches the predicate of this diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index dc077a9..910c4c5 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -220,6 +220,17 @@ static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) { N->setNext(CPPM); } +/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a +/// specified kind. Return null if we didn't find one otherwise return the +/// matcher. +static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) { + for (; M; M = M->getNext()) + if (M->getKind() == Kind) + return M; + return 0; +} + + /// FactorNodes - Turn matches like this: /// Scope /// OPC_CheckType i32 @@ -287,19 +298,46 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { // we can merge anything else into this matching group. unsigned Scan = OptionIdx; while (1) { - while (Scan != e && Optn->isContradictory(OptionsToMatch[Scan])) - ++Scan; + // If we ran out of stuff to scan, we're done. + if (Scan == e) break; + + Matcher *ScanMatcher = OptionsToMatch[Scan]; - // Ok, we found something that isn't known to be contradictory. If it is - // equal, we can merge it into the set of nodes to factor, if not, we have - // to cease factoring. - if (Scan == e || !Optn->isEqual(OptionsToMatch[Scan])) break; + // If we found an entry that matches out matcher, merge it into the set to + // handle. + if (Optn->isEqual(ScanMatcher)) { + // If is equal after all, add the option to EqualMatchers and remove it + // from OptionsToMatch. + EqualMatchers.push_back(ScanMatcher); + OptionsToMatch.erase(OptionsToMatch.begin()+Scan); + --e; + continue; + } + + // If the option we're checking for contradicts the start of the list, + // skip over it. + if (Optn->isContradictory(ScanMatcher)) { + ++Scan; + continue; + } - // If is equal after all, add the option to EqualMatchers and remove it - // from OptionsToMatch. - EqualMatchers.push_back(OptionsToMatch[Scan]); - OptionsToMatch.erase(OptionsToMatch.begin()+Scan); - --e; + // If we're scanning for a simple node, see if it occurs later in the + // sequence. If so, and if we can move it up, it might be contradictory + // or the same as what we're looking for. If so, reorder it. + if (Optn->isSimplePredicateOrRecordNode()) { + Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind()); + if (M2 != 0 && M2 != ScanMatcher && + M2->canMoveBefore(ScanMatcher) && + (M2->isEqual(Optn) || M2->isContradictory(Optn))) { + Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2); + M2->setNext(MatcherWithoutM2); + OptionsToMatch[Scan] = M2; + continue; + } + } + + // Otherwise, we don't know how to handle this entry, we have to bail. + break; } if (Scan != e && @@ -363,9 +401,11 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { // we can convert this Scope to be a OpcodeSwitch instead. bool AllOpcodeChecks = true, AllTypeChecks = true; for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { - if (!isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) { + // Check to see if this breaks a series of CheckOpcodeMatchers. + if (AllOpcodeChecks && + !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) { #if 0 - if (i > 3 && AllOpcodeChecks) { + if (i > 3) { errs() << "FAILING OPC #" << i << "\n"; NewOptionsToMatch[i]->dump(); } @@ -373,20 +413,28 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { AllOpcodeChecks = false; } - if (!isa<CheckTypeMatcher>(NewOptionsToMatch[i]) || - // iPTR checks could alias any other case without us knowing, don't - // bother with them. - cast<CheckTypeMatcher>(NewOptionsToMatch[i])->getType() == MVT::iPTR) { + // Check to see if this breaks a series of CheckTypeMatcher's. + if (AllTypeChecks) { + CheckTypeMatcher *CTM = + cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], + Matcher::CheckType)); + if (CTM == 0 || + // iPTR checks could alias any other case without us knowing, don't + // bother with them. + CTM->getType() == MVT::iPTR || + // If the CheckType isn't at the start of the list, see if we can move + // it there. + !CTM->canMoveBefore(NewOptionsToMatch[i])) { #if 0 - if (i > 3 && AllTypeChecks) { - errs() << "FAILING TYPE #" << i << "\n"; - NewOptionsToMatch[i]->dump(); - } + if (i > 3 && AllTypeChecks) { + errs() << "FAILING TYPE #" << i << "\n"; + NewOptionsToMatch[i]->dump(); + } #endif - AllTypeChecks = false; + AllTypeChecks = false; + } } } - // TODO: Can also do CheckChildNType. // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot. if (AllOpcodeChecks) { @@ -405,16 +453,42 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { // If all the options are CheckType's, we can form the SwitchType, woot. if (AllTypeChecks) { - DenseSet<unsigned> Types; + DenseMap<unsigned, unsigned> TypeEntry; SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases; for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { - CheckTypeMatcher *CTM = cast<CheckTypeMatcher>(NewOptionsToMatch[i]); - assert(Types.insert(CTM->getType()).second && - "Duplicate types not factored?"); - Cases.push_back(std::make_pair(CTM->getType(), CTM->getNext())); + CheckTypeMatcher *CTM = + cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], + Matcher::CheckType)); + Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM); + MVT::SimpleValueType CTMTy = CTM->getType(); + delete CTM; + + unsigned &Entry = TypeEntry[CTMTy]; + if (Entry != 0) { + // If we have unfactored duplicate types, then we should factor them. + Matcher *PrevMatcher = Cases[Entry-1].second; + if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) { + SM->setNumChildren(SM->getNumChildren()+1); + SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM); + continue; + } + + Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM }; + Cases[Entry-1].second = new ScopeMatcher(Entries, 2); + continue; + } + + Entry = Cases.size()+1; + Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM)); } - MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size())); + if (Cases.size() != 1) { + MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size())); + } else { + // If we factored and ended up with one case, create it now. + MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first)); + MatcherPtr->setNext(Cases[0].second); + } return; } diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index a7de2b7..20fbc6c 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -353,8 +353,6 @@ def isExpectedFail(xfails, xtargets, target_triple): return True -import re - def parseIntegratedTestScript(test): """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET' @@ -387,21 +385,7 @@ def parseIntegratedTestScript(test): script = [] xfails = [] xtargets = [] - ignoredAny = False for ln in open(sourcepath): - conditional = re.search('IF\((.+?)\((.+?)\)\):', ln) - if conditional: - ln = ln[conditional.end():] - condition = conditional.group(1) - value = conditional.group(2) - - # Actually test the condition. - if condition not in test.config.conditions: - return (Test.UNRESOLVED, "unknown condition '"+condition+"'") - if not test.config.conditions[condition](value): - ignoredAny = True - continue - if 'RUN:' in ln: # Isolate the command to run. index = ln.index('RUN:') @@ -438,8 +422,6 @@ def parseIntegratedTestScript(test): # Verify the script contains a run line. if not script: - if ignoredAny: - return (Test.UNSUPPORTED, "Test has only ignored run lines") return (Test.UNRESOLVED, "Test has no run line!") if script[-1][-1] == '\\': diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py index d6f2a4d..dd905ef 100644 --- a/utils/lit/lit/TestingConfig.py +++ b/utils/lit/lit/TestingConfig.py @@ -28,8 +28,7 @@ class TestingConfig: on_clone = None, test_exec_root = None, test_source_root = None, - excludes = [], - conditions = {}) + excludes = []) if os.path.exists(path): # FIXME: Improve detection and error reporting of errors in the @@ -55,7 +54,7 @@ class TestingConfig: def __init__(self, parent, name, suffixes, test_format, environment, substitutions, unsupported, on_clone, - test_exec_root, test_source_root, excludes, conditions): + test_exec_root, test_source_root, excludes): self.parent = parent self.name = str(name) self.suffixes = set(suffixes) @@ -67,7 +66,6 @@ class TestingConfig: self.test_exec_root = test_exec_root self.test_source_root = test_source_root self.excludes = set(excludes) - self.conditions = dict(conditions) def clone(self, path): # FIXME: Chain implementations? @@ -77,7 +75,7 @@ class TestingConfig: self.environment, self.substitutions, self.unsupported, self.on_clone, self.test_exec_root, self.test_source_root, - self.excludes, self.conditions) + self.excludes) if cfg.on_clone: cfg.on_clone(self, cfg, path) return cfg diff --git a/utils/unittest/UnitTestMain/Makefile b/utils/unittest/UnitTestMain/Makefile index 328d5e2..5c10049 100644 --- a/utils/unittest/UnitTestMain/Makefile +++ b/utils/unittest/UnitTestMain/Makefile @@ -14,7 +14,13 @@ include $(LEVEL)/Makefile.config LIBRARYNAME = UnitTestMain BUILD_ARCHIVE = 1 REQUIRES_RTTI = 1 + CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS) +CPP.Flags += -DGTEST_HAS_RTTI=0 +# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not +# supported by Clang, so force googletest to use its own tuple implementation. +# When we import googletest >=1.4.0, we can drop this line. +CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0 include $(LEVEL)/Makefile.common diff --git a/utils/unittest/googletest/Makefile b/utils/unittest/googletest/Makefile index 15bbf4e..1ec979d 100644 --- a/utils/unittest/googletest/Makefile +++ b/utils/unittest/googletest/Makefile @@ -14,8 +14,18 @@ include $(LEVEL)/Makefile.config LIBRARYNAME = GoogleTest BUILD_ARCHIVE = 1 REQUIRES_RTTI = 1 + +# Note that these flags are duplicated when building individual tests in +# unittests/Makefile.unittest and ../UnitTestMain/Makefile; ensure that any +# changes are made to both. CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS) +CPP.Flags += -DGTEST_HAS_RTTI=0 +# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not +# supported by Clang, so force googletest to use its own tuple implementation. +# When we import googletest >=1.4.0, we can drop this line. +CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0 + ifeq ($(HOST_OS),MingW) CPP.Flags += -DGTEST_OS_WINDOWS=1 |