1//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines an interface that allows bugpoint to choose different
10// combinations of optimizations to run on the selected input. Bugpoint will
11// run these optimizations and record the success/failure of each. This way
12// we can hopefully spot bugs in the optimizations.
13//
14//===----------------------------------------------------------------------===//
15
16#include "BugDriver.h"
17#include "llvm/Support/FileSystem.h"
18#include "llvm/Support/raw_ostream.h"
19#include <random>
20using namespace llvm;
21
22Error
23BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
24  setPassesToRun(AllPasses);
25  outs() << "Starting bug finding procedure...\n\n";
26
27  // Creating a reference output if necessary
28  if (Error E = initializeExecutionEnvironment())
29    return E;
30
31  outs() << "\n";
32  if (ReferenceOutputFile.empty()) {
33    outs() << "Generating reference output from raw program: \n";
34    if (Error E = createReferenceFile(*Program))
35      return E;
36  }
37
38  std::mt19937 randomness(std::random_device{}());
39  unsigned num = 1;
40  while (1) {
41    //
42    // Step 1: Randomize the order of the optimizer passes.
43    //
44    std::shuffle(PassesToRun.begin(), PassesToRun.end(), randomness);
45
46    //
47    // Step 2: Run optimizer passes on the program and check for success.
48    //
49    outs() << "Running selected passes on program to test for crash: ";
50    for (int i = 0, e = PassesToRun.size(); i != e; i++) {
51      outs() << "-" << PassesToRun[i] << " ";
52    }
53
54    std::string Filename;
55    if (runPasses(*Program, PassesToRun, Filename, false)) {
56      outs() << "\n";
57      outs() << "Optimizer passes caused failure!\n\n";
58      return debugOptimizerCrash();
59    } else {
60      outs() << "Combination " << num << " optimized successfully!\n";
61    }
62
63    //
64    // Step 3: Compile the optimized code.
65    //
66    outs() << "Running the code generator to test for a crash: ";
67    if (Error E = compileProgram(*Program)) {
68      outs() << "\n*** compileProgram threw an exception: ";
69      outs() << toString(std::move(E));
70      return debugCodeGeneratorCrash();
71    }
72    outs() << '\n';
73
74    //
75    // Step 4: Run the program and compare its output to the reference
76    // output (created above).
77    //
78    outs() << "*** Checking if passes caused miscompliation:\n";
79    Expected<bool> Diff = diffProgram(*Program, Filename, "", false);
80    if (Error E = Diff.takeError()) {
81      errs() << toString(std::move(E));
82      return debugCodeGeneratorCrash();
83    }
84    if (*Diff) {
85      outs() << "\n*** diffProgram returned true!\n";
86      Error E = debugMiscompilation();
87      if (!E)
88        return Error::success();
89    }
90    outs() << "\n*** diff'd output matches!\n";
91
92    sys::fs::remove(Filename);
93
94    outs() << "\n\n";
95    num++;
96  } // end while
97
98  // Unreachable.
99}
100