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> 20 using namespace llvm; 21 22 Error 23 BugDriver::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 (true) { 41 // 42 // Step 1: Randomize the order of the optimizer passes. 43 // 44 llvm::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