Path: blob/main/contrib/llvm-project/llvm/lib/Support/DeltaAlgorithm.cpp
35232 views
//===--- DeltaAlgorithm.cpp - A Set Minimization Algorithm -----*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//===----------------------------------------------------------------------===//67#include "llvm/ADT/DeltaAlgorithm.h"8#include <algorithm>9#include <iterator>10#include <set>11using namespace llvm;1213DeltaAlgorithm::~DeltaAlgorithm() = default;1415bool DeltaAlgorithm::GetTestResult(const changeset_ty &Changes) {16if (FailedTestsCache.count(Changes))17return false;1819bool Result = ExecuteOneTest(Changes);20if (!Result)21FailedTestsCache.insert(Changes);2223return Result;24}2526void DeltaAlgorithm::Split(const changeset_ty &S, changesetlist_ty &Res) {27// FIXME: Allow clients to provide heuristics for improved splitting.2829// FIXME: This is really slow.30changeset_ty LHS, RHS;31unsigned idx = 0, N = S.size() / 2;32for (changeset_ty::const_iterator it = S.begin(),33ie = S.end(); it != ie; ++it, ++idx)34((idx < N) ? LHS : RHS).insert(*it);35if (!LHS.empty())36Res.push_back(LHS);37if (!RHS.empty())38Res.push_back(RHS);39}4041DeltaAlgorithm::changeset_ty42DeltaAlgorithm::Delta(const changeset_ty &Changes,43const changesetlist_ty &Sets) {44// Invariant: union(Res) == Changes45UpdatedSearchState(Changes, Sets);4647// If there is nothing left we can remove, we are done.48if (Sets.size() <= 1)49return Changes;5051// Look for a passing subset.52changeset_ty Res;53if (Search(Changes, Sets, Res))54return Res;5556// Otherwise, partition the sets if possible; if not we are done.57changesetlist_ty SplitSets;58for (const changeset_ty &Set : Sets)59Split(Set, SplitSets);60if (SplitSets.size() == Sets.size())61return Changes;6263return Delta(Changes, SplitSets);64}6566bool DeltaAlgorithm::Search(const changeset_ty &Changes,67const changesetlist_ty &Sets,68changeset_ty &Res) {69// FIXME: Parallelize.70for (changesetlist_ty::const_iterator it = Sets.begin(),71ie = Sets.end(); it != ie; ++it) {72// If the test passes on this subset alone, recurse.73if (GetTestResult(*it)) {74changesetlist_ty Sets;75Split(*it, Sets);76Res = Delta(*it, Sets);77return true;78}7980// Otherwise, if we have more than two sets, see if test passes on the81// complement.82if (Sets.size() > 2) {83// FIXME: This is really slow.84changeset_ty Complement;85std::set_difference(Changes.begin(), Changes.end(), it->begin(),86it->end(),87std::inserter(Complement, Complement.begin()));88if (GetTestResult(Complement)) {89changesetlist_ty ComplementSets;90ComplementSets.insert(ComplementSets.end(), Sets.begin(), it);91ComplementSets.insert(ComplementSets.end(), it + 1, Sets.end());92Res = Delta(Complement, ComplementSets);93return true;94}95}96}9798return false;99}100101DeltaAlgorithm::changeset_ty DeltaAlgorithm::Run(const changeset_ty &Changes) {102// Check empty set first to quickly find poor test functions.103if (GetTestResult(changeset_ty()))104return changeset_ty();105106// Otherwise run the real delta algorithm.107changesetlist_ty Sets;108Split(Changes, Sets);109110return Delta(Changes, Sets);111}112113114