1 //===-- reduce-chunk-list.cpp - Reduce a chunks list to its minimal size --===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // See the llvm-project/llvm/docs/ProgrammersManual.rst to see how to use this
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ADT/DenseSet.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/DebugCounter.h"
17 #include "llvm/Support/Program.h"
21 cl::opt
<std::string
> ReproductionCmd(cl::Positional
, cl::Required
);
23 cl::opt
<std::string
> StartChunks(cl::Positional
, cl::Required
);
25 cl::opt
<bool> Pessimist("pessimist", cl::init(false));
27 using Chunk
= DebugCounter::Chunk
;
31 SmallVector
<Chunk
> simplifyChunksList(ArrayRef
<Chunk
> Chunks
) {
32 SmallVector
<Chunk
> Res
;
33 Res
.push_back(Chunks
.front());
34 for (unsigned Idx
= 1; Idx
< Chunks
.size(); Idx
++) {
35 if (Chunks
[Idx
].Begin
== Res
.back().End
+ 1)
36 Res
.back().End
= Chunks
[Idx
].End
;
38 Res
.push_back(Chunks
[Idx
]);
43 bool isStillInteresting(ArrayRef
<Chunk
> Chunks
) {
44 SmallVector
<Chunk
> SimpleChunks
= simplifyChunksList(Chunks
);
48 raw_string_ostream
OS(ChunkStr
);
49 DebugCounter::printChunks(OS
, SimpleChunks
);
52 errs() << "Checking with: " << ChunkStr
<< "\n";
54 std::vector
<StringRef
> Argv
;
55 Argv
.push_back(ReproductionCmd
);
56 Argv
.push_back(ChunkStr
);
60 int Result
= sys::ExecuteAndWait(Argv
[0], Argv
, std::nullopt
, {}, 0, 0,
61 &ErrMsg
, &ExecutionFailed
);
62 if (ExecutionFailed
) {
63 errs() << "failed to execute : " << Argv
[0] << " : " << ErrMsg
<< "\n";
67 bool Res
= Result
!= 0;
69 errs() << "SUCCESS : Still Interesting\n";
71 errs() << "FAILURE : Not Interesting\n";
76 bool increaseGranularity(SmallVector
<Chunk
> &Chunks
) {
77 errs() << "Increasing granularity\n";
78 SmallVector
<Chunk
> NewChunks
;
79 bool SplitOne
= false;
81 for (auto &C
: Chunks
) {
82 if (C
.Begin
== C
.End
) {
83 NewChunks
.push_back(C
);
85 int Half
= (C
.Begin
+ C
.End
) / 2;
86 NewChunks
.push_back({C
.Begin
, Half
});
87 NewChunks
.push_back({Half
+ 1, C
.End
});
92 Chunks
= std::move(NewChunks
);
99 int main(int argc
, char **argv
) {
100 cl::ParseCommandLineOptions(argc
, argv
);
102 SmallVector
<Chunk
> CurrChunks
;
103 if (DebugCounter::parseChunks(StartChunks
, CurrChunks
)) {
107 auto Program
= sys::findProgramByName(ReproductionCmd
);
109 errs() << "failed to find command : " << ReproductionCmd
<< "\n";
112 ReproductionCmd
.setValue(Program
.get());
114 errs() << "Input Checking:\n";
115 if (!isStillInteresting(CurrChunks
)) {
116 errs() << "starting chunks are not interesting\n";
119 if (CurrChunks
.size() == 1)
120 increaseGranularity(CurrChunks
);
122 while (increaseGranularity(CurrChunks
))
125 for (int Idx
= (CurrChunks
.size() - 1); Idx
>= 0; Idx
--) {
126 if (CurrChunks
.size() == 1)
129 Chunk Testing
= CurrChunks
[Idx
];
130 errs() << "Trying to remove : ";
131 Testing
.print(errs());
134 CurrChunks
.erase(CurrChunks
.begin() + Idx
);
136 if (!isStillInteresting(CurrChunks
))
137 CurrChunks
.insert(CurrChunks
.begin() + Idx
, Testing
);
139 bool HasSplit
= increaseGranularity(CurrChunks
);
144 errs() << "Minimal Chunks = ";
145 DebugCounter::printChunks(llvm::errs(), simplifyChunksList(CurrChunks
));