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