diff options
Diffstat (limited to 'tools/bugpoint/ListReducer.h')
-rw-r--r-- | tools/bugpoint/ListReducer.h | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h new file mode 100644 index 0000000000..1751c77b18 --- /dev/null +++ b/tools/bugpoint/ListReducer.h @@ -0,0 +1,86 @@ +//===- ListReducer.h - Trim down list while retaining property --*- C++ -*-===// +// +// This class is to be used as a base class for operations that want to zero in +// on a subset of the input which still causes the bug we are tracking. +// +//===----------------------------------------------------------------------===// + +#ifndef BUGPOINT_LIST_REDUCER_H +#define BUGPOINT_LIST_REDUCER_H + +#include <vector> + +template<typename ElTy> +struct ListReducer { + enum TestResult { + NoFailure, // No failure of the predicate was detected + KeepSuffix, // The suffix alone satisfies the predicate + KeepPrefix, // The prefix alone satisfies the predicate + }; + + // doTest - This virtual function should be overriden by subclasses to + // implement the test desired. The testcase is only required to test to see + // if the Kept list still satisfies the property, but if it is going to check + // the prefix anyway, it can. + // + virtual TestResult doTest(const std::vector<ElTy> &Prefix, + const std::vector<ElTy> &Kept) = 0; + + // reduceList - This function attempts to reduce the length of the specified + // list while still maintaining the "test" property. This is the core of the + // "work" that bugpoint does. + // + void reduceList(std::vector<ElTy> &TheList) { + unsigned MidTop = TheList.size(); + while (MidTop > 1) { + unsigned Mid = MidTop / 2; + std::vector<ElTy> Prefix(TheList.begin()+Mid, TheList.end()); + std::vector<ElTy> Kept (TheList.begin(), TheList.begin()+Mid); + + switch (doTest(Prefix, Kept)) { + case KeepSuffix: + // The property still holds. We can just drop the prefix elements, and + // shorten the list to the "kept" elements. + TheList.swap(Kept); + MidTop = TheList.size(); + break; + case KeepPrefix: + // The predicate still holds, shorten the list to the prefix elements. + TheList.swap(Prefix); + MidTop = TheList.size(); + break; + case NoFailure: + // Otherwise the property doesn't hold. Some of the elements we removed + // must be neccesary to maintain the property. + MidTop = Mid; + break; + } + } + + // Okay, we trimmed as much off the top and the bottom of the list as we + // could. If there is more two elements in the list, try deleting interior + // elements and testing that. + // + if (TheList.size() > 2) { + bool Changed = true; + std::vector<ElTy> EmptyList; + while (Changed) { + Changed = false; + std::vector<ElTy> TrimmedList; + for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts + std::vector<ElTy> TestList(TheList); + TestList.erase(TestList.begin()+i); + + if (doTest(EmptyList, TestList) == KeepSuffix) { + // We can trim down the list! + TheList.swap(TestList); + --i; // Don't skip an element of the list + Changed = true; + } + } + } + } + } +}; + +#endif |