1*ff53d469SDaniel Dunbar //===--- DeltaAlgorithm.h - A Set Minimization Algorithm -------*- C++ -*--===// 2*ff53d469SDaniel Dunbar // 3*ff53d469SDaniel Dunbar // The LLVM Compiler Infrastructure 4*ff53d469SDaniel Dunbar // 5*ff53d469SDaniel Dunbar // This file is distributed under the University of Illinois Open Source 6*ff53d469SDaniel Dunbar // License. See LICENSE.TXT for details. 7*ff53d469SDaniel Dunbar //===----------------------------------------------------------------------===// 8*ff53d469SDaniel Dunbar 9*ff53d469SDaniel Dunbar #include "llvm/ADT/DeltaAlgorithm.h" 10*ff53d469SDaniel Dunbar #include <algorithm> 11*ff53d469SDaniel Dunbar using namespace llvm; 12*ff53d469SDaniel Dunbar 13*ff53d469SDaniel Dunbar bool DeltaAlgorithm::GetTestResult(const changeset_ty &Changes) { 14*ff53d469SDaniel Dunbar if (FailedTestsCache.count(Changes)) 15*ff53d469SDaniel Dunbar return false; 16*ff53d469SDaniel Dunbar 17*ff53d469SDaniel Dunbar bool Result = ExecuteOneTest(Changes); 18*ff53d469SDaniel Dunbar if (!Result) 19*ff53d469SDaniel Dunbar FailedTestsCache.insert(Changes); 20*ff53d469SDaniel Dunbar 21*ff53d469SDaniel Dunbar return Result; 22*ff53d469SDaniel Dunbar } 23*ff53d469SDaniel Dunbar 24*ff53d469SDaniel Dunbar void DeltaAlgorithm::Split(const changeset_ty &S, changesetlist_ty &Res) { 25*ff53d469SDaniel Dunbar // FIXME: Allow clients to provide heuristics for improved splitting. 26*ff53d469SDaniel Dunbar 27*ff53d469SDaniel Dunbar // FIXME: This is really slow. 28*ff53d469SDaniel Dunbar changeset_ty LHS, RHS; 29*ff53d469SDaniel Dunbar unsigned idx = 0; 30*ff53d469SDaniel Dunbar for (changeset_ty::const_iterator it = S.begin(), 31*ff53d469SDaniel Dunbar ie = S.end(); it != ie; ++it, ++idx) 32*ff53d469SDaniel Dunbar ((idx & 1) ? LHS : RHS).insert(*it); 33*ff53d469SDaniel Dunbar if (!LHS.empty()) 34*ff53d469SDaniel Dunbar Res.push_back(LHS); 35*ff53d469SDaniel Dunbar if (!RHS.empty()) 36*ff53d469SDaniel Dunbar Res.push_back(RHS); 37*ff53d469SDaniel Dunbar } 38*ff53d469SDaniel Dunbar 39*ff53d469SDaniel Dunbar DeltaAlgorithm::changeset_ty 40*ff53d469SDaniel Dunbar DeltaAlgorithm::Delta(const changeset_ty &Changes, 41*ff53d469SDaniel Dunbar const changesetlist_ty &Sets) { 42*ff53d469SDaniel Dunbar // Invariant: union(Res) == Changes 43*ff53d469SDaniel Dunbar UpdatedSearchState(Changes, Sets); 44*ff53d469SDaniel Dunbar 45*ff53d469SDaniel Dunbar // If there is nothing left we can remove, we are done. 46*ff53d469SDaniel Dunbar if (Sets.size() <= 1) 47*ff53d469SDaniel Dunbar return Changes; 48*ff53d469SDaniel Dunbar 49*ff53d469SDaniel Dunbar // Look for a passing subset. 50*ff53d469SDaniel Dunbar changeset_ty Res; 51*ff53d469SDaniel Dunbar if (Search(Changes, Sets, Res)) 52*ff53d469SDaniel Dunbar return Res; 53*ff53d469SDaniel Dunbar 54*ff53d469SDaniel Dunbar // Otherwise, partition the sets if possible; if not we are done. 55*ff53d469SDaniel Dunbar changesetlist_ty SplitSets; 56*ff53d469SDaniel Dunbar for (changesetlist_ty::const_iterator it = Sets.begin(), 57*ff53d469SDaniel Dunbar ie = Sets.end(); it != ie; ++it) 58*ff53d469SDaniel Dunbar Split(*it, SplitSets); 59*ff53d469SDaniel Dunbar if (SplitSets.size() == Sets.size()) 60*ff53d469SDaniel Dunbar return Changes; 61*ff53d469SDaniel Dunbar 62*ff53d469SDaniel Dunbar return Delta(Changes, SplitSets); 63*ff53d469SDaniel Dunbar } 64*ff53d469SDaniel Dunbar 65*ff53d469SDaniel Dunbar bool DeltaAlgorithm::Search(const changeset_ty &Changes, 66*ff53d469SDaniel Dunbar const changesetlist_ty &Sets, 67*ff53d469SDaniel Dunbar changeset_ty &Res) { 68*ff53d469SDaniel Dunbar // FIXME: Parallelize. 69*ff53d469SDaniel Dunbar for (changesetlist_ty::const_iterator it = Sets.begin(), 70*ff53d469SDaniel Dunbar ie = Sets.end(); it != ie; ++it) { 71*ff53d469SDaniel Dunbar // If the test passes on this subset alone, recurse. 72*ff53d469SDaniel Dunbar if (GetTestResult(*it)) { 73*ff53d469SDaniel Dunbar changesetlist_ty Sets; 74*ff53d469SDaniel Dunbar Split(*it, Sets); 75*ff53d469SDaniel Dunbar Res = Delta(*it, Sets); 76*ff53d469SDaniel Dunbar return true; 77*ff53d469SDaniel Dunbar } 78*ff53d469SDaniel Dunbar 79*ff53d469SDaniel Dunbar // Otherwise, if we have more than two sets, see if test passes on the 80*ff53d469SDaniel Dunbar // complement. 81*ff53d469SDaniel Dunbar if (Sets.size() > 2) { 82*ff53d469SDaniel Dunbar // FIXME: This is really slow. 83*ff53d469SDaniel Dunbar changeset_ty Complement; 84*ff53d469SDaniel Dunbar std::set_difference( 85*ff53d469SDaniel Dunbar Changes.begin(), Changes.end(), it->begin(), it->end(), 86*ff53d469SDaniel Dunbar std::insert_iterator<changeset_ty>(Complement, Complement.begin())); 87*ff53d469SDaniel Dunbar if (GetTestResult(Complement)) { 88*ff53d469SDaniel Dunbar changesetlist_ty ComplementSets; 89*ff53d469SDaniel Dunbar ComplementSets.insert(ComplementSets.end(), Sets.begin(), it); 90*ff53d469SDaniel Dunbar ComplementSets.insert(ComplementSets.end(), it + 1, Sets.end()); 91*ff53d469SDaniel Dunbar Res = Delta(Complement, ComplementSets); 92*ff53d469SDaniel Dunbar return true; 93*ff53d469SDaniel Dunbar } 94*ff53d469SDaniel Dunbar } 95*ff53d469SDaniel Dunbar } 96*ff53d469SDaniel Dunbar 97*ff53d469SDaniel Dunbar return false; 98*ff53d469SDaniel Dunbar } 99*ff53d469SDaniel Dunbar 100*ff53d469SDaniel Dunbar DeltaAlgorithm::changeset_ty DeltaAlgorithm::Run(const changeset_ty &Changes) { 101*ff53d469SDaniel Dunbar // Check empty set first to quickly find poor test functions. 102*ff53d469SDaniel Dunbar if (GetTestResult(changeset_ty())) 103*ff53d469SDaniel Dunbar return changeset_ty(); 104*ff53d469SDaniel Dunbar 105*ff53d469SDaniel Dunbar // Otherwise run the real delta algorithm. 106*ff53d469SDaniel Dunbar changesetlist_ty Sets; 107*ff53d469SDaniel Dunbar Split(Changes, Sets); 108*ff53d469SDaniel Dunbar 109*ff53d469SDaniel Dunbar return Delta(Changes, Sets); 110*ff53d469SDaniel Dunbar } 111