1193323Sed//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// 2193323Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9314564Sdim// This file defines an interface that allows bugpoint to choose different 10314564Sdim// combinations of optimizations to run on the selected input. Bugpoint will 11193323Sed// run these optimizations and record the success/failure of each. This way 12193323Sed// we can hopefully spot bugs in the optimizations. 13193323Sed// 14193323Sed//===----------------------------------------------------------------------===// 15193323Sed 16193323Sed#include "BugDriver.h" 17261991Sdim#include "llvm/Support/FileSystem.h" 18198090Srdivacky#include "llvm/Support/raw_ostream.h" 19321369Sdim#include <random> 20193323Sedusing namespace llvm; 21193323Sed 22314564SdimError 23314564SdimBugDriver::runManyPasses(const std::vector<std::string> &AllPasses) { 24193323Sed setPassesToRun(AllPasses); 25198090Srdivacky outs() << "Starting bug finding procedure...\n\n"; 26314564Sdim 27193323Sed // Creating a reference output if necessary 28314564Sdim if (Error E = initializeExecutionEnvironment()) 29314564Sdim return E; 30314564Sdim 31198090Srdivacky outs() << "\n"; 32193323Sed if (ReferenceOutputFile.empty()) { 33198090Srdivacky outs() << "Generating reference output from raw program: \n"; 34341825Sdim if (Error E = createReferenceFile(*Program)) 35314564Sdim return E; 36193323Sed } 37314564Sdim 38321369Sdim std::mt19937 randomness(std::random_device{}()); 39193323Sed unsigned num = 1; 40314564Sdim while (1) { 41193323Sed // 42193323Sed // Step 1: Randomize the order of the optimizer passes. 43193323Sed // 44321369Sdim std::shuffle(PassesToRun.begin(), PassesToRun.end(), randomness); 45314564Sdim 46193323Sed // 47193323Sed // Step 2: Run optimizer passes on the program and check for success. 48193323Sed // 49198090Srdivacky outs() << "Running selected passes on program to test for crash: "; 50314564Sdim for (int i = 0, e = PassesToRun.size(); i != e; i++) { 51212793Sdim outs() << "-" << PassesToRun[i] << " "; 52193323Sed } 53314564Sdim 54193323Sed std::string Filename; 55341825Sdim if (runPasses(*Program, PassesToRun, Filename, false)) { 56198090Srdivacky outs() << "\n"; 57198090Srdivacky outs() << "Optimizer passes caused failure!\n\n"; 58314564Sdim return debugOptimizerCrash(); 59193323Sed } else { 60198090Srdivacky outs() << "Combination " << num << " optimized successfully!\n"; 61193323Sed } 62314564Sdim 63193323Sed // 64193323Sed // Step 3: Compile the optimized code. 65193323Sed // 66198090Srdivacky outs() << "Running the code generator to test for a crash: "; 67341825Sdim if (Error E = compileProgram(*Program)) { 68198090Srdivacky outs() << "\n*** compileProgram threw an exception: "; 69314564Sdim outs() << toString(std::move(E)); 70314564Sdim return debugCodeGeneratorCrash(); 71193323Sed } 72207618Srdivacky outs() << '\n'; 73314564Sdim 74193323Sed // 75314564Sdim // Step 4: Run the program and compare its output to the reference 76193323Sed // output (created above). 77193323Sed // 78198090Srdivacky outs() << "*** Checking if passes caused miscompliation:\n"; 79341825Sdim Expected<bool> Diff = diffProgram(*Program, Filename, "", false); 80314564Sdim if (Error E = Diff.takeError()) { 81314564Sdim errs() << toString(std::move(E)); 82314564Sdim return debugCodeGeneratorCrash(); 83314564Sdim } 84314564Sdim if (*Diff) { 85207618Srdivacky outs() << "\n*** diffProgram returned true!\n"; 86314564Sdim Error E = debugMiscompilation(); 87314564Sdim if (!E) 88314564Sdim return Error::success(); 89207618Srdivacky } 90207618Srdivacky outs() << "\n*** diff'd output matches!\n"; 91314564Sdim 92261991Sdim sys::fs::remove(Filename); 93314564Sdim 94198090Srdivacky outs() << "\n\n"; 95193323Sed num++; 96314564Sdim } // end while 97314564Sdim 98193323Sed // Unreachable. 99193323Sed} 100