improve compareFunction extraction (fix use of uninit memory, etc)
MODIFY
llvm_util/compare.cpp
llvm_util/compare.cpp
+// Copyright (c) 2018-present The Alive2 Authors.
+// Distributed under the MIT license that can be found in the LICENSE file.
+
#include "llvm_util/compare.h"
#include "llvm_util/llvm2alive.h"
#include "llvm_util/llvm_optimizer.h"
#include "smt/smt.h"
#include "tools/transform.h"
-#include "util/version.h"
#include <sstream>
#include <utility>
@@ -15,8 +17,6 @@ using namespace llvm_util;
namespace {
-llvm::ExitOnError ExitOnErr;
-
struct Results {
Transform t;
string error;
@@ -40,8 +40,8 @@ struct Results {
Results verify(llvm::Function &F1, llvm::Function &F2,
llvm::TargetLibraryInfoWrapperPass &TLI,
- smt::smt_initializer &smt_init, ostream *out,
- bool print_transform = false, bool always_verify = false) {
+ smt::smt_initializer &smt_init, ostream &out,
+ bool print_transform, bool always_verify) {
auto fn1 = llvm2alive(F1, TLI.getTLI(F1), true);
if (!fn1)
return Results::Error("Could not translate '" + F1.getName().str() +
@@ -62,7 +62,7 @@ Results verify(llvm::Function &F1, llvm::Function &F2,
r.t.tgt.print(ss2);
if (std::move(ss1).str() == std::move(ss2).str()) {
if (print_transform)
- r.t.print(*out, {});
+ r.t.print(out, {});
r.status = Results::SYNTACTIC_EQ;
return r;
}
@@ -73,7 +73,7 @@ Results verify(llvm::Function &F1, llvm::Function &F2,
TransformVerify verifier(r.t, false);
if (print_transform)
- r.t.print(*out, {});
+ r.t.print(out, {});
{
auto types = verifier.getTypings();
@@ -95,18 +95,15 @@ Results verify(llvm::Function &F1, llvm::Function &F2,
} // namespace
-bool compareFunctions(llvm::Function &F1, llvm::Function &F2,
- llvm::TargetLibraryInfoWrapperPass &TLI,
- smt::smt_initializer &smt_init, tv_stats &stats,
- const tv_opts &opts, ostream *out) {
- auto r = verify(F1, F2, TLI, smt_init, out, !opts.quiet, opts.always_verify);
+bool Verifier::compareFunctions(llvm::Function &F1, llvm::Function &F2) {
+ auto r = verify(F1, F2, TLI, smt_init, out, !quiet, always_verify);
if (r.status == Results::ERROR) {
- *out << "ERROR: " << r.error;
- ++stats.num_errors;
+ out << "ERROR: " << r.error;
+ ++num_errors;
return true;
}
- if (opts.print_dot) {
+ if (print_dot) {
r.t.src.writeDot("src");
r.t.tgt.writeDot("tgt");
}
@@ -117,36 +114,36 @@ bool compareFunctions(llvm::Function &F1, llvm::Function &F2,
break;
case Results::SYNTACTIC_EQ:
- *out << "Transformation seems to be correct! (syntactically equal)\n\n";
- ++stats.num_correct;
+ out << "Transformation seems to be correct! (syntactically equal)\n\n";
+ ++num_correct;
break;
case Results::CORRECT:
- *out << "Transformation seems to be correct!\n\n";
- ++stats.num_correct;
+ out << "Transformation seems to be correct!\n\n";
+ ++num_correct;
break;
case Results::TYPE_CHECKER_FAILED:
- *out << "Transformation doesn't verify!\n"
+ out << "Transformation doesn't verify!\n"
"ERROR: program doesn't type check!\n\n";
- ++stats.num_errors;
+ ++num_errors;
return true;
case Results::UNSOUND:
- *out << "Transformation doesn't verify!\n\n";
- if (!opts.quiet)
- *out << r.errs << endl;
- ++stats.num_unsound;
+ out << "Transformation doesn't verify!\n\n";
+ if (!quiet)
+ out << r.errs << endl;
+ ++num_unsound;
return false;
case Results::FAILED_TO_PROVE:
- *out << r.errs << endl;
- ++stats.num_failed;
+ out << r.errs << endl;
+ ++num_failed;
return true;
}
- if (opts.bidirectional) {
- r = verify(F2, F1, TLI, smt_init, out, false, opts.always_verify);
+ if (bidirectional) {
+ r = verify(F2, F1, TLI, smt_init, out, false, always_verify);
switch (r.status) {
case Results::ERROR:
case Results::TYPE_CHECKER_FAILED:
@@ -155,19 +152,19 @@ bool compareFunctions(llvm::Function &F1, llvm::Function &F2,
case Results::SYNTACTIC_EQ:
case Results::CORRECT:
- *out << "These functions seem to be equivalent!\n\n";
+ out << "These functions seem to be equivalent!\n\n";
return true;
case Results::FAILED_TO_PROVE:
- *out << "Failed to verify the reverse transformation\n\n";
- if (!opts.quiet)
- *out << r.errs << endl;
+ out << "Failed to verify the reverse transformation\n\n";
+ if (!quiet)
+ out << r.errs << endl;
return true;
case Results::UNSOUND:
- *out << "Reverse transformation doesn't verify!\n\n";
- if (!opts.quiet)
- *out << r.errs << endl;
+ out << "Reverse transformation doesn't verify!\n\n";
+ if (!quiet)
+ out << r.errs << endl;
return false;
}
}

MODIFY
llvm_util/compare.h
llvm_util/compare.h
-#include "smt/smt.h"
+#pragma once
+
+// Copyright (c) 2018-present The Alive2 Authors.
+// Distributed under the MIT license that can be found in the LICENSE file.
+#include "smt/smt.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Function.h"
+#include <ostream>
-struct tv_stats {
- unsigned num_correct, num_unsound, num_failed, num_errors;
-};
+namespace llvm_util {
+
+struct Verifier {
+ llvm::TargetLibraryInfoWrapperPass &TLI;
+ smt::smt_initializer &smt_init;
+ std::ostream &out;
+ unsigned num_correct = 0;
+ unsigned num_unsound = 0;
+ unsigned num_failed = 0;
+ unsigned num_errors = 0;
+ bool quiet = false;
+ bool always_verify = false;
+ bool print_dot = false;
+ bool bidirectional = false;
+
+ Verifier(llvm::TargetLibraryInfoWrapperPass &TLI,
+ smt::smt_initializer &smt_init, std::ostream &out)
+ : TLI(TLI), smt_init(smt_init), out(out) {}
-struct tv_opts {
- tv_opts(bool quiet, bool always_verify, bool print_dot, bool bidirectional)
- : quiet(quiet), always_verify(always_verify), print_dot(print_dot),
- bidirectional(bidirectional) {}
- bool quiet, always_verify, print_dot, bidirectional;
+ bool compareFunctions(llvm::Function &F1, llvm::Function &F2);
};
-bool compareFunctions(llvm::Function &F1, llvm::Function &F2,
- llvm::TargetLibraryInfoWrapperPass &TLI,
- smt::smt_initializer &smt_init, tv_stats &stats,
- const tv_opts &opts, std::ostream *out);
+}

MODIFY
tools/alive-tv.cpp
tools/alive-tv.cpp
// Copyright (c) 2018-present The Alive2 Authors.
// Distributed under the MIT license that can be found in the LICENSE file.
-#include "cache/cache.h"
#include "llvm_util/compare.h"
#include "llvm_util/llvm2alive.h"
#include "llvm_util/llvm_optimizer.h"
@@ -88,10 +87,6 @@ std::unique_ptr<llvm::Module> openInputFile(llvm::LLVMContext &Context,
return M;
}
-optional<smt::smt_initializer> smt_init;
-unique_ptr<Cache> cache;
-tv_stats stats;
-
llvm::Function *findFunction(llvm::Module &M, const string &FName) {
for (auto &F : M) {
if (F.isDeclaration())
@@ -141,7 +136,6 @@ convenient way to demonstrate an existing optimizer bug.
llvm::cl::HideUnrelatedOptions(alive_cmdargs);
llvm::cl::ParseCommandLineOptions(argc, argv, Usage);
- const tv_opts opts(opt_quiet, opt_always_verify, opt_print_dot, opt_bidirectional);
auto M1 = openInputFile(Context, opt_file1);
if (!M1.get()) {
@@ -157,14 +151,19 @@ convenient way to demonstrate an existing optimizer bug.
llvm::TargetLibraryInfoWrapperPass TLI(targetTriple);
llvm_util::initializer llvm_util_init(*out, DL);
- smt_init.emplace();
+ smt::smt_initializer smt_init;
+ Verifier verifier(TLI, smt_init, *out);
+ verifier.quiet = opt_quiet;
+ verifier.always_verify = opt_always_verify;
+ verifier.print_dot = opt_print_dot;
+ verifier.bidirectional = opt_bidirectional;
unique_ptr<llvm::Module> M2;
if (opt_file2.empty()) {
auto SRC = findFunction(*M1, opt_src_fn);
auto TGT = findFunction(*M1, opt_tgt_fn);
if (SRC && TGT) {
- compareFunctions(*SRC, *TGT, TLI, *smt_init, stats, opts, out);
+ verifier.compareFunctions(*SRC, *TGT);
goto end;
} else {
M2 = CloneModule(*M1);
@@ -204,7 +203,7 @@ convenient way to demonstrate an existing optimizer bug.
M2_anon_count++;
if ((F1.getName().empty() && (M1_anon_count == M2_anon_count)) ||
(F1.getName() == F2.getName())) {
- if (!compareFunctions(F1, F2, TLI, *smt_init, stats, opts, out))
+ if (!verifier.compareFunctions(F1, F2))
if (opt_error_fatal)
goto end;
break;
@@ -213,10 +212,10 @@ convenient way to demonstrate an existing optimizer bug.
}
*out << "Summary:\n"
- " " << stats.num_correct << " correct transformations\n"
- " " << stats.num_unsound << " incorrect transformations\n"
- " " << stats.num_failed << " failed-to-prove transformations\n"
- " " << stats.num_errors << " Alive2 errors\n";
+ " " << verifier.num_correct << " correct transformations\n"
+ " " << verifier.num_unsound << " incorrect transformations\n"
+ " " << verifier.num_failed << " failed-to-prove transformations\n"
+ " " << verifier.num_errors << " Alive2 errors\n";
end:
if (opt_smt_stats)
@@ -227,5 +226,5 @@ end:
if (opt_alias_stats)
IR::Memory::printAliasStats(*out);
- return stats.num_errors > 0;
+ return verifier.num_errors > 0;
}

MODIFY
tools/quick-fuzz.cpp
tools/quick-fuzz.cpp
// Copyright (c) 2018-present The Alive2 Authors.
// Distributed under the MIT license that can be found in the LICENSE file.
-#include "cache/cache.h"
#include "llvm_util/compare.h"
#include "llvm_util/llvm2alive.h"
#include "llvm_util/llvm_optimizer.h"
@@ -76,10 +75,6 @@ llvm::cl::opt<string> optPass(
"https://llvm.org/docs/NewPassManager.html#invoking-opt"),
llvm::cl::cat(alive_cmdargs), llvm::cl::init("O2"));
-optional<smt::smt_initializer> smt_init;
-unique_ptr<Cache> cache;
-tv_stats stats;
-
// FIXME we might want to be able to specify these on the command
// line, but these should be pretty good defaults
const int MaxBBs = 50;
@@ -87,7 +82,7 @@ const int MaxWidth = 20;
const int MaxCounters = 16;
const int MaxBoolParams = 16;
-std::unique_ptr<std::mt19937_64> Rand;
+std::optional<std::mt19937_64> Rand;
long choose(long Choices) {
std::uniform_int_distribution<int> Dist(0, Choices - 1);
@@ -97,7 +92,7 @@ long choose(long Choices) {
void init() {
auto Seed = (opt_rand_seed == 0) ? (std::random_device{}()) : opt_rand_seed;
cout << "seed = " << Seed << endl;
- Rand = std::make_unique<std::mt19937_64>(Seed);
+ Rand.emplace(Seed);
}
llvm::CmpInst::Predicate random_pred() {
@@ -259,7 +254,6 @@ reduced using llvm-reduce.
llvm::cl::HideUnrelatedOptions(alive_cmdargs);
llvm::cl::ParseCommandLineOptions(argc, argv, Usage);
- tv_opts opts(opt_quiet, opt_always_verify, opt_print_dot, opt_bidirectional);
unique_ptr<llvm::Module> MDummy;
#define ARGS_MODULE_VAR MDummy
@@ -267,12 +261,25 @@ reduced using llvm-reduce.
init();
+ llvm::Module M1("fuzz", Context);
+ auto &DL = M1.getDataLayout();
+ llvm::Triple targetTriple(M1.getTargetTriple());
+ llvm::TargetLibraryInfoWrapperPass TLI(targetTriple);
+
+ llvm_util::initializer llvm_util_init(*out, DL);
+ smt::smt_initializer smt_init;
+ Verifier verifier(TLI, smt_init, *out);
+ verifier.quiet = opt_quiet;
+ verifier.always_verify = opt_always_verify;
+ verifier.print_dot = opt_print_dot;
+ verifier.bidirectional = opt_bidirectional;
+
for (int rep = 0; rep < opt_num_reps; ++rep) {
- auto M1 = make_unique<llvm::Module>("fuzz", Context);
- generate(&*M1);
+ M1.dropAllReferences();
+ generate(&M1);
if (opt_run_sroa) {
- auto err = optimize_module(M1.get(), "sroa,dse");
+ auto err = optimize_module(&M1, "sroa,dse");
assert(err.empty());
}
@@ -284,62 +291,49 @@ reduced using llvm-reduce.
llvm::raw_fd_ostream output_file(output_fn.str(), EC);
if (EC)
llvm::report_fatal_error("Couldn't open output file, exiting");
- llvm::WriteBitcodeToFile(*M1.get(), output_file);
+ llvm::WriteBitcodeToFile(M1, output_file);
}
if (opt_skip_alive)
continue;
- auto &DL = M1.get()->getDataLayout();
- llvm::Triple targetTriple(M1.get()->getTargetTriple());
- llvm::TargetLibraryInfoWrapperPass TLI(targetTriple);
-
- llvm_util::initializer llvm_util_init(*out, DL);
- smt_init.emplace();
-
- unique_ptr<llvm::Module> M2;
- M2 = CloneModule(*M1);
+ auto M2 = CloneModule(M1);
auto err = optimize_module(M2.get(), optPass);
if (!err.empty()) {
*out << "Error parsing list of LLVM passes: " << err << '\n';
return -1;
}
- if (M1.get()->getTargetTriple() != M2.get()->getTargetTriple()) {
+ if (M1.getTargetTriple() != M2.get()->getTargetTriple()) {
*out << "Modules have different target triples\n";
return -1;
}
- auto *F1 = M1->getFunction("f");
+ auto *F1 = M1.getFunction("f");
auto *F2 = M2->getFunction("f");
assert(F1 && F2);
- if (!compareFunctions(*F1, *F2, TLI, *smt_init, stats, opts, out))
+ if (!verifier.compareFunctions(*F1, *F2))
if (opt_error_fatal)
goto end;
}
*out << "Summary:\n"
" "
- << stats.num_correct
+ << verifier.num_correct
<< " correct transformations\n"
" "
- << stats.num_unsound
+ << verifier.num_unsound
<< " incorrect transformations\n"
" "
- << stats.num_failed
+ << verifier.num_failed
<< " failed-to-prove transformations\n"
" "
- << stats.num_errors << " Alive2 errors\n";
+ << verifier.num_errors << " Alive2 errors\n";
end:
if (opt_smt_stats)
smt::solver_print_stats(*out);
- smt_init.reset();
-
- if (opt_alias_stats)
- IR::Memory::printAliasStats(*out);
-
- return stats.num_errors > 0;
+ return verifier.num_errors > 0;
}

improve compareFunction extraction (fix use of uninit memory, etc)