0ab2ef9927ac5787efbd91215839c23dbf69e47f
[oota-llvm.git] / tools / bugpoint / ListReducer.h
1 //===- ListReducer.h - Trim down list while retaining property --*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This class is to be used as a base class for operations that want to zero in
11 // on a subset of the input which still causes the bug we are tracking.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef BUGPOINT_LIST_REDUCER_H
16 #define BUGPOINT_LIST_REDUCER_H
17
18 #include <vector>
19
20 template<typename ElTy>
21 struct ListReducer {
22   enum TestResult {
23     NoFailure,         // No failure of the predicate was detected
24     KeepSuffix,        // The suffix alone satisfies the predicate
25     KeepPrefix,        // The prefix alone satisfies the predicate
26   };
27
28   // doTest - This virtual function should be overriden by subclasses to
29   // implement the test desired.  The testcase is only required to test to see
30   // if the Kept list still satisfies the property, but if it is going to check
31   // the prefix anyway, it can.
32   //
33   virtual TestResult doTest(std::vector<ElTy> &Prefix,
34                             std::vector<ElTy> &Kept) = 0;
35
36   // reduceList - This function attempts to reduce the length of the specified
37   // list while still maintaining the "test" property.  This is the core of the
38   // "work" that bugpoint does.
39   //
40   bool reduceList(std::vector<ElTy> &TheList) {
41     std::vector<ElTy> empty;
42     switch (doTest(TheList, empty)) {
43     case KeepPrefix:
44       if (TheList.size() == 1) // we are done, it's the base case and it fails
45         return true;
46       else 
47         break; // there's definitely an error, but we need to narrow it down
48
49     case KeepSuffix:
50       // cannot be reached!
51       std::cerr << "bugpoint ListReducer internal error: selected empty set.\n";
52       abort();
53
54     case NoFailure:
55       return false; // there is no failure with the full set of passes/funcs!
56     }
57
58     unsigned MidTop = TheList.size();
59     while (MidTop > 1) {
60       unsigned Mid = MidTop / 2;
61       std::vector<ElTy> Prefix(TheList.begin(), TheList.begin()+Mid);
62       std::vector<ElTy> Suffix(TheList.begin()+Mid, TheList.end());
63
64       switch (doTest(Prefix, Suffix)) {
65       case KeepSuffix:
66         // The property still holds.  We can just drop the prefix elements, and
67         // shorten the list to the "kept" elements.
68         TheList.swap(Suffix);
69         MidTop = TheList.size();
70         break;
71       case KeepPrefix:
72         // The predicate still holds, shorten the list to the prefix elements.
73         TheList.swap(Prefix);
74         MidTop = TheList.size();
75         break;
76       case NoFailure:
77         // Otherwise the property doesn't hold.  Some of the elements we removed
78         // must be necessary to maintain the property.
79         MidTop = Mid;
80         break;
81       }
82     }
83
84     // Okay, we trimmed as much off the top and the bottom of the list as we
85     // could.  If there is more two elements in the list, try deleting interior
86     // elements and testing that.
87     //
88     if (TheList.size() > 2) {
89       bool Changed = true;
90       std::vector<ElTy> EmptyList;
91       while (Changed) {
92         Changed = false;
93         std::vector<ElTy> TrimmedList;
94         for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts
95           std::vector<ElTy> TestList(TheList);
96           TestList.erase(TestList.begin()+i);
97
98           if (doTest(EmptyList, TestList) == KeepSuffix) {
99             // We can trim down the list!
100             TheList.swap(TestList);
101             --i;  // Don't skip an element of the list
102             Changed = true;
103           }
104         }
105       }
106     }
107
108     return true; // there are some failure and we've narrowed them down
109   }
110 };
111
112 #endif