10b57cec5SDimitry Andric //===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the bugpoint internals that narrow down compilation crashes
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "BugDriver.h"
140b57cec5SDimitry Andric #include "ListReducer.h"
150b57cec5SDimitry Andric #include "ToolRunner.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
190b57cec5SDimitry Andric #include "llvm/IR/CFG.h"
200b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
210b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
23480093f4SDimitry Andric #include "llvm/IR/InstIterator.h"
240b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
250b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
260b57cec5SDimitry Andric #include "llvm/IR/Module.h"
270b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h"
280b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
290b57cec5SDimitry Andric #include "llvm/Pass.h"
300b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
310b57cec5SDimitry Andric #include "llvm/Support/FileUtilities.h"
320b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
330b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
340b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
35480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
360b57cec5SDimitry Andric #include <set>
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric namespace {
400b57cec5SDimitry Andric cl::opt<bool> KeepMain("keep-main",
410b57cec5SDimitry Andric                        cl::desc("Force function reduction to keep main"),
420b57cec5SDimitry Andric                        cl::init(false));
430b57cec5SDimitry Andric cl::opt<bool> NoGlobalRM("disable-global-remove",
440b57cec5SDimitry Andric                          cl::desc("Do not remove global variables"),
450b57cec5SDimitry Andric                          cl::init(false));
460b57cec5SDimitry Andric 
47480093f4SDimitry Andric cl::opt<bool> NoAttributeRM("disable-attribute-remove",
48480093f4SDimitry Andric                          cl::desc("Do not remove function attributes"),
49480093f4SDimitry Andric                          cl::init(false));
50480093f4SDimitry Andric 
510b57cec5SDimitry Andric cl::opt<bool> ReplaceFuncsWithNull(
520b57cec5SDimitry Andric     "replace-funcs-with-null",
530b57cec5SDimitry Andric     cl::desc("When stubbing functions, replace all uses will null"),
540b57cec5SDimitry Andric     cl::init(false));
550b57cec5SDimitry Andric cl::opt<bool> DontReducePassList("disable-pass-list-reduction",
560b57cec5SDimitry Andric                                  cl::desc("Skip pass list reduction steps"),
570b57cec5SDimitry Andric                                  cl::init(false));
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric cl::opt<bool> NoNamedMDRM("disable-namedmd-remove",
600b57cec5SDimitry Andric                           cl::desc("Do not remove global named metadata"),
610b57cec5SDimitry Andric                           cl::init(false));
620b57cec5SDimitry Andric cl::opt<bool> NoStripDebugInfo("disable-strip-debuginfo",
630b57cec5SDimitry Andric                                cl::desc("Do not strip debug info metadata"),
640b57cec5SDimitry Andric                                cl::init(false));
650b57cec5SDimitry Andric cl::opt<bool> NoStripDebugTypeInfo("disable-strip-debug-types",
660b57cec5SDimitry Andric                                cl::desc("Do not strip debug type info metadata"),
670b57cec5SDimitry Andric                                cl::init(false));
680b57cec5SDimitry Andric cl::opt<bool> VerboseErrors("verbose-errors",
690b57cec5SDimitry Andric                             cl::desc("Print the output of crashing program"),
700b57cec5SDimitry Andric                             cl::init(false));
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
isValidModule(std::unique_ptr<Module> & M,bool ExitOnFailure=true)7306c3fb27SDimitry Andric static bool isValidModule(std::unique_ptr<Module> &M,
7406c3fb27SDimitry Andric                           bool ExitOnFailure = true) {
7506c3fb27SDimitry Andric   if (!llvm::verifyModule(*M.get(), &llvm::errs()))
7606c3fb27SDimitry Andric     return true;
7706c3fb27SDimitry Andric 
7806c3fb27SDimitry Andric   if (ExitOnFailure) {
7906c3fb27SDimitry Andric     llvm::errs() << "verify failed!\n";
8006c3fb27SDimitry Andric     exit(1);
8106c3fb27SDimitry Andric   }
8206c3fb27SDimitry Andric   return false;
8306c3fb27SDimitry Andric }
8406c3fb27SDimitry Andric 
850b57cec5SDimitry Andric namespace llvm {
860b57cec5SDimitry Andric class ReducePassList : public ListReducer<std::string> {
870b57cec5SDimitry Andric   BugDriver &BD;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric public:
ReducePassList(BugDriver & bd)900b57cec5SDimitry Andric   ReducePassList(BugDriver &bd) : BD(bd) {}
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   // Return true iff running the "removed" passes succeeds, and running the
930b57cec5SDimitry Andric   // "Kept" passes fail when run on the output of the "removed" passes.  If we
940b57cec5SDimitry Andric   // return true, we update the current module of bugpoint.
950b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<std::string> &Removed,
960b57cec5SDimitry Andric                               std::vector<std::string> &Kept) override;
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric Expected<ReducePassList::TestResult>
doTest(std::vector<std::string> & Prefix,std::vector<std::string> & Suffix)1010b57cec5SDimitry Andric ReducePassList::doTest(std::vector<std::string> &Prefix,
1020b57cec5SDimitry Andric                        std::vector<std::string> &Suffix) {
1030b57cec5SDimitry Andric   std::string PrefixOutput;
1040b57cec5SDimitry Andric   std::unique_ptr<Module> OrigProgram;
1050b57cec5SDimitry Andric   if (!Prefix.empty()) {
1060b57cec5SDimitry Andric     outs() << "Checking to see if these passes crash: "
1070b57cec5SDimitry Andric            << getPassesString(Prefix) << ": ";
1080b57cec5SDimitry Andric     if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))
1090b57cec5SDimitry Andric       return KeepPrefix;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     OrigProgram = std::move(BD.Program);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     BD.Program = parseInputFile(PrefixOutput, BD.getContext());
1140b57cec5SDimitry Andric     if (BD.Program == nullptr) {
1150b57cec5SDimitry Andric       errs() << BD.getToolName() << ": Error reading bitcode file '"
1160b57cec5SDimitry Andric              << PrefixOutput << "'!\n";
1170b57cec5SDimitry Andric       exit(1);
1180b57cec5SDimitry Andric     }
1190b57cec5SDimitry Andric     sys::fs::remove(PrefixOutput);
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)
1230b57cec5SDimitry Andric          << ": ";
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   if (BD.runPasses(BD.getProgram(), Suffix))
1260b57cec5SDimitry Andric     return KeepSuffix; // The suffix crashes alone...
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   // Nothing failed, restore state...
1290b57cec5SDimitry Andric   if (OrigProgram)
1300b57cec5SDimitry Andric     BD.Program = std::move(OrigProgram);
1310b57cec5SDimitry Andric   return NoFailure;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric using BugTester = bool (*)(const BugDriver &, Module *);
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric namespace {
1370b57cec5SDimitry Andric /// ReduceCrashingGlobalInitializers - This works by removing global variable
1380b57cec5SDimitry Andric /// initializers and seeing if the program still crashes. If it does, then we
1390b57cec5SDimitry Andric /// keep that program and try again.
1400b57cec5SDimitry Andric class ReduceCrashingGlobalInitializers : public ListReducer<GlobalVariable *> {
1410b57cec5SDimitry Andric   BugDriver &BD;
1420b57cec5SDimitry Andric   BugTester TestFn;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric public:
ReduceCrashingGlobalInitializers(BugDriver & bd,BugTester testFn)1450b57cec5SDimitry Andric   ReduceCrashingGlobalInitializers(BugDriver &bd, BugTester testFn)
1460b57cec5SDimitry Andric       : BD(bd), TestFn(testFn) {}
1470b57cec5SDimitry Andric 
doTest(std::vector<GlobalVariable * > & Prefix,std::vector<GlobalVariable * > & Kept)1480b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<GlobalVariable *> &Prefix,
1490b57cec5SDimitry Andric                               std::vector<GlobalVariable *> &Kept) override {
1500b57cec5SDimitry Andric     if (!Kept.empty() && TestGlobalVariables(Kept))
1510b57cec5SDimitry Andric       return KeepSuffix;
1520b57cec5SDimitry Andric     if (!Prefix.empty() && TestGlobalVariables(Prefix))
1530b57cec5SDimitry Andric       return KeepPrefix;
1540b57cec5SDimitry Andric     return NoFailure;
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   bool TestGlobalVariables(std::vector<GlobalVariable *> &GVs);
1580b57cec5SDimitry Andric };
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
TestGlobalVariables(std::vector<GlobalVariable * > & GVs)1610b57cec5SDimitry Andric bool ReduceCrashingGlobalInitializers::TestGlobalVariables(
1620b57cec5SDimitry Andric     std::vector<GlobalVariable *> &GVs) {
1630b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
1640b57cec5SDimitry Andric   ValueToValueMapTy VMap;
1650b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   // Convert list to set for fast lookup...
1680b57cec5SDimitry Andric   std::set<GlobalVariable *> GVSet;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   for (unsigned i = 0, e = GVs.size(); i != e; ++i) {
1710b57cec5SDimitry Andric     GlobalVariable *CMGV = cast<GlobalVariable>(VMap[GVs[i]]);
1720b57cec5SDimitry Andric     assert(CMGV && "Global Variable not in module?!");
1730b57cec5SDimitry Andric     GVSet.insert(CMGV);
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   outs() << "Checking for crash with only these global variables: ";
1770b57cec5SDimitry Andric   PrintGlobalVariableList(GVs);
1780b57cec5SDimitry Andric   outs() << ": ";
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // Loop over and delete any global variables which we aren't supposed to be
1810b57cec5SDimitry Andric   // playing with...
1820b57cec5SDimitry Andric   for (GlobalVariable &I : M->globals())
1830b57cec5SDimitry Andric     if (I.hasInitializer() && !GVSet.count(&I)) {
1840b57cec5SDimitry Andric       DeleteGlobalInitializer(&I);
1850b57cec5SDimitry Andric       I.setLinkage(GlobalValue::ExternalLinkage);
1860b57cec5SDimitry Andric       I.setComdat(nullptr);
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   // Try running the hacked up program...
1900b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
1910b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric     // Make sure to use global variable pointers that point into the now-current
1940b57cec5SDimitry Andric     // module.
1950b57cec5SDimitry Andric     GVs.assign(GVSet.begin(), GVSet.end());
1960b57cec5SDimitry Andric     return true;
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   return false;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric namespace {
2030b57cec5SDimitry Andric /// ReduceCrashingFunctions reducer - This works by removing functions and
2040b57cec5SDimitry Andric /// seeing if the program still crashes. If it does, then keep the newer,
2050b57cec5SDimitry Andric /// smaller program.
2060b57cec5SDimitry Andric ///
2070b57cec5SDimitry Andric class ReduceCrashingFunctions : public ListReducer<Function *> {
2080b57cec5SDimitry Andric   BugDriver &BD;
2090b57cec5SDimitry Andric   BugTester TestFn;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric public:
ReduceCrashingFunctions(BugDriver & bd,BugTester testFn)2120b57cec5SDimitry Andric   ReduceCrashingFunctions(BugDriver &bd, BugTester testFn)
2130b57cec5SDimitry Andric       : BD(bd), TestFn(testFn) {}
2140b57cec5SDimitry Andric 
doTest(std::vector<Function * > & Prefix,std::vector<Function * > & Kept)2150b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<Function *> &Prefix,
2160b57cec5SDimitry Andric                               std::vector<Function *> &Kept) override {
2170b57cec5SDimitry Andric     if (!Kept.empty() && TestFuncs(Kept))
2180b57cec5SDimitry Andric       return KeepSuffix;
2190b57cec5SDimitry Andric     if (!Prefix.empty() && TestFuncs(Prefix))
2200b57cec5SDimitry Andric       return KeepPrefix;
2210b57cec5SDimitry Andric     return NoFailure;
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   bool TestFuncs(std::vector<Function *> &Prefix);
2250b57cec5SDimitry Andric };
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
RemoveFunctionReferences(Module * M,const char * Name)2280b57cec5SDimitry Andric static void RemoveFunctionReferences(Module *M, const char *Name) {
2290b57cec5SDimitry Andric   auto *UsedVar = M->getGlobalVariable(Name, true);
2300b57cec5SDimitry Andric   if (!UsedVar || !UsedVar->hasInitializer())
2310b57cec5SDimitry Andric     return;
2320b57cec5SDimitry Andric   if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) {
2330b57cec5SDimitry Andric     assert(UsedVar->use_empty());
2340b57cec5SDimitry Andric     UsedVar->eraseFromParent();
2350b57cec5SDimitry Andric     return;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric   auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer());
2380b57cec5SDimitry Andric   std::vector<Constant *> Used;
2390b57cec5SDimitry Andric   for (Value *V : OldUsedVal->operand_values()) {
2400b57cec5SDimitry Andric     Constant *Op = cast<Constant>(V->stripPointerCasts());
2410b57cec5SDimitry Andric     if (!Op->isNullValue()) {
2420b57cec5SDimitry Andric       Used.push_back(cast<Constant>(V));
2430b57cec5SDimitry Andric     }
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric   auto *NewValElemTy = OldUsedVal->getType()->getElementType();
2460b57cec5SDimitry Andric   auto *NewValTy = ArrayType::get(NewValElemTy, Used.size());
2470b57cec5SDimitry Andric   auto *NewUsedVal = ConstantArray::get(NewValTy, Used);
2480b57cec5SDimitry Andric   UsedVar->mutateType(NewUsedVal->getType()->getPointerTo());
2490b57cec5SDimitry Andric   UsedVar->setInitializer(NewUsedVal);
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
TestFuncs(std::vector<Function * > & Funcs)2520b57cec5SDimitry Andric bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
2530b57cec5SDimitry Andric   // If main isn't present, claim there is no problem.
2540b57cec5SDimitry Andric   if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))
2550b57cec5SDimitry Andric     return false;
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
2580b57cec5SDimitry Andric   ValueToValueMapTy VMap;
2590b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   // Convert list to set for fast lookup...
2620b57cec5SDimitry Andric   std::set<Function *> Functions;
2630b57cec5SDimitry Andric   for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
2640b57cec5SDimitry Andric     Function *CMF = cast<Function>(VMap[Funcs[i]]);
2650b57cec5SDimitry Andric     assert(CMF && "Function not in module?!");
2660b57cec5SDimitry Andric     assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty");
2670b57cec5SDimitry Andric     assert(CMF->getName() == Funcs[i]->getName() && "wrong name");
2680b57cec5SDimitry Andric     Functions.insert(CMF);
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   outs() << "Checking for crash with only these functions: ";
2720b57cec5SDimitry Andric   PrintFunctionList(Funcs);
2730b57cec5SDimitry Andric   outs() << ": ";
2740b57cec5SDimitry Andric   if (!ReplaceFuncsWithNull) {
2750b57cec5SDimitry Andric     // Loop over and delete any functions which we aren't supposed to be playing
2760b57cec5SDimitry Andric     // with...
2770b57cec5SDimitry Andric     for (Function &I : *M)
2780b57cec5SDimitry Andric       if (!I.isDeclaration() && !Functions.count(&I))
2790b57cec5SDimitry Andric         DeleteFunctionBody(&I);
2800b57cec5SDimitry Andric   } else {
2810b57cec5SDimitry Andric     std::vector<GlobalValue *> ToRemove;
2820b57cec5SDimitry Andric     // First, remove aliases to functions we're about to purge.
2830b57cec5SDimitry Andric     for (GlobalAlias &Alias : M->aliases()) {
284349cc55cSDimitry Andric       GlobalObject *Root = Alias.getAliaseeObject();
28581ad6265SDimitry Andric       auto *F = dyn_cast<Function>(Root);
2860b57cec5SDimitry Andric       if (F) {
2870b57cec5SDimitry Andric         if (Functions.count(F))
2880b57cec5SDimitry Andric           // We're keeping this function.
2890b57cec5SDimitry Andric           continue;
2900b57cec5SDimitry Andric       } else if (Root->isNullValue()) {
2910b57cec5SDimitry Andric         // This referenced a globalalias that we've already replaced,
2920b57cec5SDimitry Andric         // so we still need to replace this alias.
29381ad6265SDimitry Andric       } else {
2940b57cec5SDimitry Andric         // Not a function, therefore not something we mess with.
2950b57cec5SDimitry Andric         continue;
2960b57cec5SDimitry Andric       }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric       PointerType *Ty = cast<PointerType>(Alias.getType());
2990b57cec5SDimitry Andric       Constant *Replacement = ConstantPointerNull::get(Ty);
3000b57cec5SDimitry Andric       Alias.replaceAllUsesWith(Replacement);
3010b57cec5SDimitry Andric       ToRemove.push_back(&Alias);
3020b57cec5SDimitry Andric     }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     for (Function &I : *M) {
3050b57cec5SDimitry Andric       if (!I.isDeclaration() && !Functions.count(&I)) {
3060b57cec5SDimitry Andric         PointerType *Ty = cast<PointerType>(I.getType());
3070b57cec5SDimitry Andric         Constant *Replacement = ConstantPointerNull::get(Ty);
3080b57cec5SDimitry Andric         I.replaceAllUsesWith(Replacement);
3090b57cec5SDimitry Andric         ToRemove.push_back(&I);
3100b57cec5SDimitry Andric       }
3110b57cec5SDimitry Andric     }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     for (auto *F : ToRemove) {
3140b57cec5SDimitry Andric       F->eraseFromParent();
3150b57cec5SDimitry Andric     }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric     // Finally, remove any null members from any global intrinsic.
3180b57cec5SDimitry Andric     RemoveFunctionReferences(M.get(), "llvm.used");
3190b57cec5SDimitry Andric     RemoveFunctionReferences(M.get(), "llvm.compiler.used");
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric   // Try running the hacked up program...
3220b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
3230b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric     // Make sure to use function pointers that point into the now-current
3260b57cec5SDimitry Andric     // module.
3270b57cec5SDimitry Andric     Funcs.assign(Functions.begin(), Functions.end());
3280b57cec5SDimitry Andric     return true;
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric   return false;
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric namespace {
3340b57cec5SDimitry Andric /// ReduceCrashingFunctionAttributes reducer - This works by removing
3350b57cec5SDimitry Andric /// attributes on a particular function and seeing if the program still crashes.
3360b57cec5SDimitry Andric /// If it does, then keep the newer, smaller program.
3370b57cec5SDimitry Andric ///
3380b57cec5SDimitry Andric class ReduceCrashingFunctionAttributes : public ListReducer<Attribute> {
3390b57cec5SDimitry Andric   BugDriver &BD;
3400b57cec5SDimitry Andric   std::string FnName;
3410b57cec5SDimitry Andric   BugTester TestFn;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric public:
ReduceCrashingFunctionAttributes(BugDriver & bd,const std::string & FnName,BugTester testFn)3440b57cec5SDimitry Andric   ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,
3450b57cec5SDimitry Andric                                    BugTester testFn)
3460b57cec5SDimitry Andric       : BD(bd), FnName(FnName), TestFn(testFn) {}
3470b57cec5SDimitry Andric 
doTest(std::vector<Attribute> & Prefix,std::vector<Attribute> & Kept)3480b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<Attribute> &Prefix,
3490b57cec5SDimitry Andric                               std::vector<Attribute> &Kept) override {
3500b57cec5SDimitry Andric     if (!Kept.empty() && TestFuncAttrs(Kept))
3510b57cec5SDimitry Andric       return KeepSuffix;
3520b57cec5SDimitry Andric     if (!Prefix.empty() && TestFuncAttrs(Prefix))
3530b57cec5SDimitry Andric       return KeepPrefix;
3540b57cec5SDimitry Andric     return NoFailure;
3550b57cec5SDimitry Andric   }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   bool TestFuncAttrs(std::vector<Attribute> &Attrs);
3580b57cec5SDimitry Andric };
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
TestFuncAttrs(std::vector<Attribute> & Attrs)3610b57cec5SDimitry Andric bool ReduceCrashingFunctionAttributes::TestFuncAttrs(
3620b57cec5SDimitry Andric     std::vector<Attribute> &Attrs) {
3630b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
3640b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram());
3650b57cec5SDimitry Andric   Function *F = M->getFunction(FnName);
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   // Build up an AttributeList from the attributes we've been given by the
3680b57cec5SDimitry Andric   // reducer.
36904eeddc0SDimitry Andric   AttrBuilder AB(M->getContext());
3700b57cec5SDimitry Andric   for (auto A : Attrs)
3710b57cec5SDimitry Andric     AB.addAttribute(A);
3720b57cec5SDimitry Andric   AttributeList NewAttrs;
373349cc55cSDimitry Andric   NewAttrs = NewAttrs.addFnAttributes(BD.getContext(), AB);
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   // Set this new list of attributes on the function.
3760b57cec5SDimitry Andric   F->setAttributes(NewAttrs);
3770b57cec5SDimitry Andric 
378480093f4SDimitry Andric   // If the attribute list includes "optnone" we need to make sure it also
379480093f4SDimitry Andric   // includes "noinline" otherwise we will get a verifier failure.
380480093f4SDimitry Andric   if (F->hasFnAttribute(Attribute::OptimizeNone))
381480093f4SDimitry Andric     F->addFnAttr(Attribute::NoInline);
382480093f4SDimitry Andric 
38306c3fb27SDimitry Andric   // If modifying the attribute list leads to invalid IR, revert the change
38406c3fb27SDimitry Andric   if (!isValidModule(M, /*ExitOnFailure=*/false))
38506c3fb27SDimitry Andric     return false;
38606c3fb27SDimitry Andric 
3870b57cec5SDimitry Andric   // Try running on the hacked up program...
3880b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
3890b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric     // Pass along the set of attributes that caused the crash.
3920b57cec5SDimitry Andric     Attrs.clear();
393349cc55cSDimitry Andric     for (Attribute A : NewAttrs.getFnAttrs()) {
3940b57cec5SDimitry Andric       Attrs.push_back(A);
3950b57cec5SDimitry Andric     }
3960b57cec5SDimitry Andric     return true;
3970b57cec5SDimitry Andric   }
3980b57cec5SDimitry Andric   return false;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric namespace {
4020b57cec5SDimitry Andric /// Simplify the CFG without completely destroying it.
4030b57cec5SDimitry Andric /// This is not well defined, but basically comes down to "try to eliminate
4040b57cec5SDimitry Andric /// unreachable blocks and constant fold terminators without deciding that
4050b57cec5SDimitry Andric /// certain undefined behavior cuts off the program at the legs".
simpleSimplifyCfg(Function & F,SmallVectorImpl<BasicBlock * > & BBs)4060b57cec5SDimitry Andric void simpleSimplifyCfg(Function &F, SmallVectorImpl<BasicBlock *> &BBs) {
4070b57cec5SDimitry Andric   if (F.empty())
4080b57cec5SDimitry Andric     return;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   for (auto *BB : BBs) {
4110b57cec5SDimitry Andric     ConstantFoldTerminator(BB);
4120b57cec5SDimitry Andric     MergeBlockIntoPredecessor(BB);
4130b57cec5SDimitry Andric   }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   // Remove unreachable blocks
4160b57cec5SDimitry Andric   // removeUnreachableBlocks can't be used here, it will turn various
4170b57cec5SDimitry Andric   // undefined behavior into unreachables, but bugpoint was the thing that
4180b57cec5SDimitry Andric   // generated the undefined behavior, and we don't want it to kill the entire
4190b57cec5SDimitry Andric   // program.
4200b57cec5SDimitry Andric   SmallPtrSet<BasicBlock *, 16> Visited;
4210b57cec5SDimitry Andric   for (auto *BB : depth_first(&F.getEntryBlock()))
4220b57cec5SDimitry Andric     Visited.insert(BB);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   SmallVector<BasicBlock *, 16> Unreachable;
4250b57cec5SDimitry Andric   for (auto &BB : F)
4260b57cec5SDimitry Andric     if (!Visited.count(&BB))
4270b57cec5SDimitry Andric       Unreachable.push_back(&BB);
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // The dead BB's may be in a dead cycle or otherwise have references to each
4300b57cec5SDimitry Andric   // other.  Because of this, we have to drop all references first, then delete
4310b57cec5SDimitry Andric   // them all at once.
4320b57cec5SDimitry Andric   for (auto *BB : Unreachable) {
4330b57cec5SDimitry Andric     for (BasicBlock *Successor : successors(&*BB))
4340b57cec5SDimitry Andric       if (Visited.count(Successor))
4350b57cec5SDimitry Andric         Successor->removePredecessor(&*BB);
4360b57cec5SDimitry Andric     BB->dropAllReferences();
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric   for (auto *BB : Unreachable)
4390b57cec5SDimitry Andric     BB->eraseFromParent();
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric /// ReduceCrashingBlocks reducer - This works by setting the terminators of
4420b57cec5SDimitry Andric /// all terminators except the specified basic blocks to a 'ret' instruction,
443fe6060f1SDimitry Andric /// then running the simplifycfg pass.  This has the effect of chopping up
4440b57cec5SDimitry Andric /// the CFG really fast which can reduce large functions quickly.
4450b57cec5SDimitry Andric ///
4460b57cec5SDimitry Andric class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {
4470b57cec5SDimitry Andric   BugDriver &BD;
4480b57cec5SDimitry Andric   BugTester TestFn;
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric public:
ReduceCrashingBlocks(BugDriver & BD,BugTester testFn)4510b57cec5SDimitry Andric   ReduceCrashingBlocks(BugDriver &BD, BugTester testFn)
4520b57cec5SDimitry Andric       : BD(BD), TestFn(testFn) {}
4530b57cec5SDimitry Andric 
doTest(std::vector<const BasicBlock * > & Prefix,std::vector<const BasicBlock * > & Kept)4540b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
4550b57cec5SDimitry Andric                               std::vector<const BasicBlock *> &Kept) override {
4560b57cec5SDimitry Andric     if (!Kept.empty() && TestBlocks(Kept))
4570b57cec5SDimitry Andric       return KeepSuffix;
4580b57cec5SDimitry Andric     if (!Prefix.empty() && TestBlocks(Prefix))
4590b57cec5SDimitry Andric       return KeepPrefix;
4600b57cec5SDimitry Andric     return NoFailure;
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
4640b57cec5SDimitry Andric };
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
TestBlocks(std::vector<const BasicBlock * > & BBs)4670b57cec5SDimitry Andric bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
4680b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
4690b57cec5SDimitry Andric   ValueToValueMapTy VMap;
4700b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   // Convert list to set for fast lookup...
4730b57cec5SDimitry Andric   SmallPtrSet<BasicBlock *, 8> Blocks;
4740b57cec5SDimitry Andric   for (unsigned i = 0, e = BBs.size(); i != e; ++i)
4750b57cec5SDimitry Andric     Blocks.insert(cast<BasicBlock>(VMap[BBs[i]]));
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   outs() << "Checking for crash with only these blocks:";
4780b57cec5SDimitry Andric   unsigned NumPrint = Blocks.size();
4790b57cec5SDimitry Andric   if (NumPrint > 10)
4800b57cec5SDimitry Andric     NumPrint = 10;
4810b57cec5SDimitry Andric   for (unsigned i = 0, e = NumPrint; i != e; ++i)
4820b57cec5SDimitry Andric     outs() << " " << BBs[i]->getName();
4830b57cec5SDimitry Andric   if (NumPrint < Blocks.size())
4840b57cec5SDimitry Andric     outs() << "... <" << Blocks.size() << " total>";
4850b57cec5SDimitry Andric   outs() << ": ";
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric   // Loop over and delete any hack up any blocks that are not listed...
4880b57cec5SDimitry Andric   for (Function &F : M->functions()) {
4890b57cec5SDimitry Andric     for (BasicBlock &BB : F) {
4900b57cec5SDimitry Andric       if (!Blocks.count(&BB) && BB.getTerminator()->getNumSuccessors()) {
4910b57cec5SDimitry Andric         // Loop over all of the successors of this block, deleting any PHI nodes
4920b57cec5SDimitry Andric         // that might include it.
4930b57cec5SDimitry Andric         for (BasicBlock *Succ : successors(&BB))
4940b57cec5SDimitry Andric           Succ->removePredecessor(&BB);
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric         Instruction *BBTerm = BB.getTerminator();
4970b57cec5SDimitry Andric         if (BBTerm->isEHPad() || BBTerm->getType()->isTokenTy())
4980b57cec5SDimitry Andric           continue;
4990b57cec5SDimitry Andric         if (!BBTerm->getType()->isVoidTy())
5000b57cec5SDimitry Andric           BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric         // Replace the old terminator instruction.
503bdd1243dSDimitry Andric         BB.back().eraseFromParent();
5040b57cec5SDimitry Andric         new UnreachableInst(BB.getContext(), &BB);
5050b57cec5SDimitry Andric       }
5060b57cec5SDimitry Andric     }
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   // The CFG Simplifier pass may delete one of the basic blocks we are
5100b57cec5SDimitry Andric   // interested in.  If it does we need to take the block out of the list.  Make
5110b57cec5SDimitry Andric   // a "persistent mapping" by turning basic blocks into <function, name> pairs.
5120b57cec5SDimitry Andric   // This won't work well if blocks are unnamed, but that is just the risk we
5130b57cec5SDimitry Andric   // have to take. FIXME: Can we just name the blocks?
5140b57cec5SDimitry Andric   std::vector<std::pair<std::string, std::string>> BlockInfo;
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   for (BasicBlock *BB : Blocks)
5175ffd83dbSDimitry Andric     BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
5185ffd83dbSDimitry Andric                            std::string(BB->getName()));
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   SmallVector<BasicBlock *, 16> ToProcess;
5210b57cec5SDimitry Andric   for (auto &F : *M) {
5220b57cec5SDimitry Andric     for (auto &BB : F)
5230b57cec5SDimitry Andric       if (!Blocks.count(&BB))
5240b57cec5SDimitry Andric         ToProcess.push_back(&BB);
5250b57cec5SDimitry Andric     simpleSimplifyCfg(F, ToProcess);
5260b57cec5SDimitry Andric     ToProcess.clear();
5270b57cec5SDimitry Andric   }
5280b57cec5SDimitry Andric   // Verify we didn't break anything
52906c3fb27SDimitry Andric   isValidModule(M);
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   // Try running on the hacked up program...
5320b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
5330b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric     // Make sure to use basic block pointers that point into the now-current
5360b57cec5SDimitry Andric     // module, and that they don't include any deleted blocks.
5370b57cec5SDimitry Andric     BBs.clear();
5380b57cec5SDimitry Andric     const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
5390b57cec5SDimitry Andric     for (const auto &BI : BlockInfo) {
5400b57cec5SDimitry Andric       Function *F = cast<Function>(GST.lookup(BI.first));
5410b57cec5SDimitry Andric       Value *V = F->getValueSymbolTable()->lookup(BI.second);
5420b57cec5SDimitry Andric       if (V && V->getType() == Type::getLabelTy(V->getContext()))
5430b57cec5SDimitry Andric         BBs.push_back(cast<BasicBlock>(V));
5440b57cec5SDimitry Andric     }
5450b57cec5SDimitry Andric     return true;
5460b57cec5SDimitry Andric   }
5470b57cec5SDimitry Andric   // It didn't crash, try something else.
5480b57cec5SDimitry Andric   return false;
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric namespace {
5520b57cec5SDimitry Andric /// ReduceCrashingConditionals reducer - This works by changing
5530b57cec5SDimitry Andric /// conditional branches to unconditional ones, then simplifying the CFG
5540b57cec5SDimitry Andric /// This has the effect of chopping up the CFG really fast which can reduce
5550b57cec5SDimitry Andric /// large functions quickly.
5560b57cec5SDimitry Andric ///
5570b57cec5SDimitry Andric class ReduceCrashingConditionals : public ListReducer<const BasicBlock *> {
5580b57cec5SDimitry Andric   BugDriver &BD;
5590b57cec5SDimitry Andric   BugTester TestFn;
5600b57cec5SDimitry Andric   bool Direction;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric public:
ReduceCrashingConditionals(BugDriver & bd,BugTester testFn,bool Direction)5630b57cec5SDimitry Andric   ReduceCrashingConditionals(BugDriver &bd, BugTester testFn, bool Direction)
5640b57cec5SDimitry Andric       : BD(bd), TestFn(testFn), Direction(Direction) {}
5650b57cec5SDimitry Andric 
doTest(std::vector<const BasicBlock * > & Prefix,std::vector<const BasicBlock * > & Kept)5660b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
5670b57cec5SDimitry Andric                               std::vector<const BasicBlock *> &Kept) override {
5680b57cec5SDimitry Andric     if (!Kept.empty() && TestBlocks(Kept))
5690b57cec5SDimitry Andric       return KeepSuffix;
5700b57cec5SDimitry Andric     if (!Prefix.empty() && TestBlocks(Prefix))
5710b57cec5SDimitry Andric       return KeepPrefix;
5720b57cec5SDimitry Andric     return NoFailure;
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
5760b57cec5SDimitry Andric };
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric 
TestBlocks(std::vector<const BasicBlock * > & BBs)5790b57cec5SDimitry Andric bool ReduceCrashingConditionals::TestBlocks(
5800b57cec5SDimitry Andric     std::vector<const BasicBlock *> &BBs) {
5810b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
5820b57cec5SDimitry Andric   ValueToValueMapTy VMap;
5830b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   // Convert list to set for fast lookup...
5860b57cec5SDimitry Andric   SmallPtrSet<const BasicBlock *, 8> Blocks;
5870b57cec5SDimitry Andric   for (const auto *BB : BBs)
5880b57cec5SDimitry Andric     Blocks.insert(cast<BasicBlock>(VMap[BB]));
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   outs() << "Checking for crash with changing conditionals to always jump to "
5910b57cec5SDimitry Andric          << (Direction ? "true" : "false") << ":";
5920b57cec5SDimitry Andric   unsigned NumPrint = Blocks.size();
5930b57cec5SDimitry Andric   if (NumPrint > 10)
5940b57cec5SDimitry Andric     NumPrint = 10;
5950b57cec5SDimitry Andric   for (unsigned i = 0, e = NumPrint; i != e; ++i)
5960b57cec5SDimitry Andric     outs() << " " << BBs[i]->getName();
5970b57cec5SDimitry Andric   if (NumPrint < Blocks.size())
5980b57cec5SDimitry Andric     outs() << "... <" << Blocks.size() << " total>";
5990b57cec5SDimitry Andric   outs() << ": ";
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   // Loop over and delete any hack up any blocks that are not listed...
6020b57cec5SDimitry Andric   for (auto &F : *M)
6030b57cec5SDimitry Andric     for (auto &BB : F)
6040b57cec5SDimitry Andric       if (!Blocks.count(&BB)) {
6050b57cec5SDimitry Andric         auto *BR = dyn_cast<BranchInst>(BB.getTerminator());
6060b57cec5SDimitry Andric         if (!BR || !BR->isConditional())
6070b57cec5SDimitry Andric           continue;
6080b57cec5SDimitry Andric         if (Direction)
6090b57cec5SDimitry Andric           BR->setCondition(ConstantInt::getTrue(BR->getContext()));
6100b57cec5SDimitry Andric         else
6110b57cec5SDimitry Andric           BR->setCondition(ConstantInt::getFalse(BR->getContext()));
6120b57cec5SDimitry Andric       }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   // The following may destroy some blocks, so we save them first
6150b57cec5SDimitry Andric   std::vector<std::pair<std::string, std::string>> BlockInfo;
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   for (const BasicBlock *BB : Blocks)
6185ffd83dbSDimitry Andric     BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
6195ffd83dbSDimitry Andric                            std::string(BB->getName()));
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   SmallVector<BasicBlock *, 16> ToProcess;
6220b57cec5SDimitry Andric   for (auto &F : *M) {
6230b57cec5SDimitry Andric     for (auto &BB : F)
6240b57cec5SDimitry Andric       if (!Blocks.count(&BB))
6250b57cec5SDimitry Andric         ToProcess.push_back(&BB);
6260b57cec5SDimitry Andric     simpleSimplifyCfg(F, ToProcess);
6270b57cec5SDimitry Andric     ToProcess.clear();
6280b57cec5SDimitry Andric   }
6290b57cec5SDimitry Andric   // Verify we didn't break anything
63006c3fb27SDimitry Andric   isValidModule(M);
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   // Try running on the hacked up program...
6330b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
6340b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     // Make sure to use basic block pointers that point into the now-current
6370b57cec5SDimitry Andric     // module, and that they don't include any deleted blocks.
6380b57cec5SDimitry Andric     BBs.clear();
6390b57cec5SDimitry Andric     const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
6400b57cec5SDimitry Andric     for (auto &BI : BlockInfo) {
6410b57cec5SDimitry Andric       auto *F = cast<Function>(GST.lookup(BI.first));
6420b57cec5SDimitry Andric       Value *V = F->getValueSymbolTable()->lookup(BI.second);
6430b57cec5SDimitry Andric       if (V && V->getType() == Type::getLabelTy(V->getContext()))
6440b57cec5SDimitry Andric         BBs.push_back(cast<BasicBlock>(V));
6450b57cec5SDimitry Andric     }
6460b57cec5SDimitry Andric     return true;
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric   // It didn't crash, try something else.
6490b57cec5SDimitry Andric   return false;
6500b57cec5SDimitry Andric }
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric namespace {
6530b57cec5SDimitry Andric /// SimplifyCFG reducer - This works by calling SimplifyCFG on each basic block
6540b57cec5SDimitry Andric /// in the program.
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {
6570b57cec5SDimitry Andric   BugDriver &BD;
6580b57cec5SDimitry Andric   BugTester TestFn;
6590b57cec5SDimitry Andric   TargetTransformInfo TTI;
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric public:
ReduceSimplifyCFG(BugDriver & bd,BugTester testFn)6620b57cec5SDimitry Andric   ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)
6630b57cec5SDimitry Andric       : BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}
6640b57cec5SDimitry Andric 
doTest(std::vector<const BasicBlock * > & Prefix,std::vector<const BasicBlock * > & Kept)6650b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
6660b57cec5SDimitry Andric                               std::vector<const BasicBlock *> &Kept) override {
6670b57cec5SDimitry Andric     if (!Kept.empty() && TestBlocks(Kept))
6680b57cec5SDimitry Andric       return KeepSuffix;
6690b57cec5SDimitry Andric     if (!Prefix.empty() && TestBlocks(Prefix))
6700b57cec5SDimitry Andric       return KeepPrefix;
6710b57cec5SDimitry Andric     return NoFailure;
6720b57cec5SDimitry Andric   }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
6750b57cec5SDimitry Andric };
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric 
TestBlocks(std::vector<const BasicBlock * > & BBs)6780b57cec5SDimitry Andric bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
6790b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
6800b57cec5SDimitry Andric   ValueToValueMapTy VMap;
6810b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   // Convert list to set for fast lookup...
6840b57cec5SDimitry Andric   SmallPtrSet<const BasicBlock *, 8> Blocks;
6850b57cec5SDimitry Andric   for (const auto *BB : BBs)
6860b57cec5SDimitry Andric     Blocks.insert(cast<BasicBlock>(VMap[BB]));
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric   outs() << "Checking for crash with CFG simplifying:";
6890b57cec5SDimitry Andric   unsigned NumPrint = Blocks.size();
6900b57cec5SDimitry Andric   if (NumPrint > 10)
6910b57cec5SDimitry Andric     NumPrint = 10;
6920b57cec5SDimitry Andric   for (unsigned i = 0, e = NumPrint; i != e; ++i)
6930b57cec5SDimitry Andric     outs() << " " << BBs[i]->getName();
6940b57cec5SDimitry Andric   if (NumPrint < Blocks.size())
6950b57cec5SDimitry Andric     outs() << "... <" << Blocks.size() << " total>";
6960b57cec5SDimitry Andric   outs() << ": ";
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   // The following may destroy some blocks, so we save them first
6990b57cec5SDimitry Andric   std::vector<std::pair<std::string, std::string>> BlockInfo;
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric   for (const BasicBlock *BB : Blocks)
7025ffd83dbSDimitry Andric     BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
7035ffd83dbSDimitry Andric                            std::string(BB->getName()));
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   // Loop over and delete any hack up any blocks that are not listed...
7060b57cec5SDimitry Andric   for (auto &F : *M)
7070b57cec5SDimitry Andric     // Loop over all of the basic blocks and remove them if they are unneeded.
7080b57cec5SDimitry Andric     for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {
7090b57cec5SDimitry Andric       if (!Blocks.count(&*BBIt)) {
7100b57cec5SDimitry Andric         ++BBIt;
7110b57cec5SDimitry Andric         continue;
7120b57cec5SDimitry Andric       }
7130b57cec5SDimitry Andric       simplifyCFG(&*BBIt++, TTI);
7140b57cec5SDimitry Andric     }
7150b57cec5SDimitry Andric   // Verify we didn't break anything
71606c3fb27SDimitry Andric   isValidModule(M);
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   // Try running on the hacked up program...
7190b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
7200b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric     // Make sure to use basic block pointers that point into the now-current
7230b57cec5SDimitry Andric     // module, and that they don't include any deleted blocks.
7240b57cec5SDimitry Andric     BBs.clear();
7250b57cec5SDimitry Andric     const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
7260b57cec5SDimitry Andric     for (auto &BI : BlockInfo) {
7270b57cec5SDimitry Andric       auto *F = cast<Function>(GST.lookup(BI.first));
7280b57cec5SDimitry Andric       Value *V = F->getValueSymbolTable()->lookup(BI.second);
7290b57cec5SDimitry Andric       if (V && V->getType() == Type::getLabelTy(V->getContext()))
7300b57cec5SDimitry Andric         BBs.push_back(cast<BasicBlock>(V));
7310b57cec5SDimitry Andric     }
7320b57cec5SDimitry Andric     return true;
7330b57cec5SDimitry Andric   }
7340b57cec5SDimitry Andric   // It didn't crash, try something else.
7350b57cec5SDimitry Andric   return false;
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric namespace {
7390b57cec5SDimitry Andric /// ReduceCrashingInstructions reducer - This works by removing the specified
7400b57cec5SDimitry Andric /// non-terminator instructions and replacing them with undef.
7410b57cec5SDimitry Andric ///
7420b57cec5SDimitry Andric class ReduceCrashingInstructions : public ListReducer<const Instruction *> {
7430b57cec5SDimitry Andric   BugDriver &BD;
7440b57cec5SDimitry Andric   BugTester TestFn;
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric public:
ReduceCrashingInstructions(BugDriver & bd,BugTester testFn)7470b57cec5SDimitry Andric   ReduceCrashingInstructions(BugDriver &bd, BugTester testFn)
7480b57cec5SDimitry Andric       : BD(bd), TestFn(testFn) {}
7490b57cec5SDimitry Andric 
doTest(std::vector<const Instruction * > & Prefix,std::vector<const Instruction * > & Kept)7500b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<const Instruction *> &Prefix,
7510b57cec5SDimitry Andric                               std::vector<const Instruction *> &Kept) override {
7520b57cec5SDimitry Andric     if (!Kept.empty() && TestInsts(Kept))
7530b57cec5SDimitry Andric       return KeepSuffix;
7540b57cec5SDimitry Andric     if (!Prefix.empty() && TestInsts(Prefix))
7550b57cec5SDimitry Andric       return KeepPrefix;
7560b57cec5SDimitry Andric     return NoFailure;
7570b57cec5SDimitry Andric   }
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric   bool TestInsts(std::vector<const Instruction *> &Prefix);
7600b57cec5SDimitry Andric };
7610b57cec5SDimitry Andric }
7620b57cec5SDimitry Andric 
TestInsts(std::vector<const Instruction * > & Insts)7630b57cec5SDimitry Andric bool ReduceCrashingInstructions::TestInsts(
7640b57cec5SDimitry Andric     std::vector<const Instruction *> &Insts) {
7650b57cec5SDimitry Andric   // Clone the program to try hacking it apart...
7660b57cec5SDimitry Andric   ValueToValueMapTy VMap;
7670b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   // Convert list to set for fast lookup...
7700b57cec5SDimitry Andric   SmallPtrSet<Instruction *, 32> Instructions;
7710b57cec5SDimitry Andric   for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
7720b57cec5SDimitry Andric     assert(!Insts[i]->isTerminator());
7730b57cec5SDimitry Andric     Instructions.insert(cast<Instruction>(VMap[Insts[i]]));
7740b57cec5SDimitry Andric   }
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric   outs() << "Checking for crash with only " << Instructions.size();
7770b57cec5SDimitry Andric   if (Instructions.size() == 1)
7780b57cec5SDimitry Andric     outs() << " instruction: ";
7790b57cec5SDimitry Andric   else
7800b57cec5SDimitry Andric     outs() << " instructions: ";
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI)
7830b57cec5SDimitry Andric     for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI)
784349cc55cSDimitry Andric       for (Instruction &Inst : llvm::make_early_inc_range(*FI)) {
785349cc55cSDimitry Andric         if (!Instructions.count(&Inst) && !Inst.isTerminator() &&
786349cc55cSDimitry Andric             !Inst.isEHPad() && !Inst.getType()->isTokenTy() &&
787349cc55cSDimitry Andric             !Inst.isSwiftError()) {
788349cc55cSDimitry Andric           if (!Inst.getType()->isVoidTy())
789bdd1243dSDimitry Andric             Inst.replaceAllUsesWith(PoisonValue::get(Inst.getType()));
790349cc55cSDimitry Andric           Inst.eraseFromParent();
7910b57cec5SDimitry Andric         }
7920b57cec5SDimitry Andric       }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric   // Verify that this is still valid.
79506c3fb27SDimitry Andric   isValidModule(M, /*ExitOnFailure=*/false);
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   // Try running on the hacked up program...
7980b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
7990b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric     // Make sure to use instruction pointers that point into the now-current
8020b57cec5SDimitry Andric     // module, and that they don't include any deleted blocks.
8030b57cec5SDimitry Andric     Insts.clear();
8040b57cec5SDimitry Andric     for (Instruction *Inst : Instructions)
8050b57cec5SDimitry Andric       Insts.push_back(Inst);
8060b57cec5SDimitry Andric     return true;
8070b57cec5SDimitry Andric   }
8080b57cec5SDimitry Andric   // It didn't crash, try something else.
8090b57cec5SDimitry Andric   return false;
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric namespace {
813480093f4SDimitry Andric /// ReduceCrashingMetadata reducer - This works by removing all metadata from
814480093f4SDimitry Andric /// the specified instructions.
815480093f4SDimitry Andric ///
816480093f4SDimitry Andric class ReduceCrashingMetadata : public ListReducer<Instruction *> {
817480093f4SDimitry Andric   BugDriver &BD;
818480093f4SDimitry Andric   BugTester TestFn;
819480093f4SDimitry Andric 
820480093f4SDimitry Andric public:
ReduceCrashingMetadata(BugDriver & bd,BugTester testFn)821480093f4SDimitry Andric   ReduceCrashingMetadata(BugDriver &bd, BugTester testFn)
822480093f4SDimitry Andric       : BD(bd), TestFn(testFn) {}
823480093f4SDimitry Andric 
doTest(std::vector<Instruction * > & Prefix,std::vector<Instruction * > & Kept)824480093f4SDimitry Andric   Expected<TestResult> doTest(std::vector<Instruction *> &Prefix,
825480093f4SDimitry Andric                               std::vector<Instruction *> &Kept) override {
826480093f4SDimitry Andric     if (!Kept.empty() && TestInsts(Kept))
827480093f4SDimitry Andric       return KeepSuffix;
828480093f4SDimitry Andric     if (!Prefix.empty() && TestInsts(Prefix))
829480093f4SDimitry Andric       return KeepPrefix;
830480093f4SDimitry Andric     return NoFailure;
831480093f4SDimitry Andric   }
832480093f4SDimitry Andric 
833480093f4SDimitry Andric   bool TestInsts(std::vector<Instruction *> &Prefix);
834480093f4SDimitry Andric };
835480093f4SDimitry Andric } // namespace
836480093f4SDimitry Andric 
TestInsts(std::vector<Instruction * > & Insts)837480093f4SDimitry Andric bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {
838480093f4SDimitry Andric   // Clone the program to try hacking it apart...
839480093f4SDimitry Andric   ValueToValueMapTy VMap;
840480093f4SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
841480093f4SDimitry Andric 
842480093f4SDimitry Andric   // Convert list to set for fast lookup...
843480093f4SDimitry Andric   SmallPtrSet<Instruction *, 32> Instructions;
844480093f4SDimitry Andric   for (Instruction *I : Insts)
845480093f4SDimitry Andric     Instructions.insert(cast<Instruction>(VMap[I]));
846480093f4SDimitry Andric 
847480093f4SDimitry Andric   outs() << "Checking for crash with metadata retained from "
848480093f4SDimitry Andric          << Instructions.size();
849480093f4SDimitry Andric   if (Instructions.size() == 1)
850480093f4SDimitry Andric     outs() << " instruction: ";
851480093f4SDimitry Andric   else
852480093f4SDimitry Andric     outs() << " instructions: ";
853480093f4SDimitry Andric 
854480093f4SDimitry Andric   // Try to drop instruction metadata from all instructions, except the ones
855480093f4SDimitry Andric   // selected in Instructions.
856480093f4SDimitry Andric   for (Function &F : *M)
857480093f4SDimitry Andric     for (Instruction &Inst : instructions(F)) {
8585ffd83dbSDimitry Andric       if (!Instructions.count(&Inst)) {
859480093f4SDimitry Andric         Inst.dropUnknownNonDebugMetadata();
860480093f4SDimitry Andric         Inst.setDebugLoc({});
861480093f4SDimitry Andric       }
862480093f4SDimitry Andric     }
863480093f4SDimitry Andric 
864480093f4SDimitry Andric   // Verify that this is still valid.
86506c3fb27SDimitry Andric   isValidModule(M, /*ExitOnFailure=*/false);
866480093f4SDimitry Andric 
867480093f4SDimitry Andric   // Try running on the hacked up program...
868480093f4SDimitry Andric   if (TestFn(BD, M.get())) {
869480093f4SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
870480093f4SDimitry Andric 
871480093f4SDimitry Andric     // Make sure to use instruction pointers that point into the now-current
872480093f4SDimitry Andric     // module, and that they don't include any deleted blocks.
873480093f4SDimitry Andric     Insts.clear();
874480093f4SDimitry Andric     for (Instruction *I : Instructions)
875480093f4SDimitry Andric       Insts.push_back(I);
876480093f4SDimitry Andric     return true;
877480093f4SDimitry Andric   }
878480093f4SDimitry Andric   // It didn't crash, try something else.
879480093f4SDimitry Andric   return false;
880480093f4SDimitry Andric }
881480093f4SDimitry Andric 
882480093f4SDimitry Andric namespace {
8830b57cec5SDimitry Andric // Reduce the list of Named Metadata nodes. We keep this as a list of
8840b57cec5SDimitry Andric // names to avoid having to convert back and forth every time.
8850b57cec5SDimitry Andric class ReduceCrashingNamedMD : public ListReducer<std::string> {
8860b57cec5SDimitry Andric   BugDriver &BD;
8870b57cec5SDimitry Andric   BugTester TestFn;
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric public:
ReduceCrashingNamedMD(BugDriver & bd,BugTester testFn)8900b57cec5SDimitry Andric   ReduceCrashingNamedMD(BugDriver &bd, BugTester testFn)
8910b57cec5SDimitry Andric       : BD(bd), TestFn(testFn) {}
8920b57cec5SDimitry Andric 
doTest(std::vector<std::string> & Prefix,std::vector<std::string> & Kept)8930b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<std::string> &Prefix,
8940b57cec5SDimitry Andric                               std::vector<std::string> &Kept) override {
8950b57cec5SDimitry Andric     if (!Kept.empty() && TestNamedMDs(Kept))
8960b57cec5SDimitry Andric       return KeepSuffix;
8970b57cec5SDimitry Andric     if (!Prefix.empty() && TestNamedMDs(Prefix))
8980b57cec5SDimitry Andric       return KeepPrefix;
8990b57cec5SDimitry Andric     return NoFailure;
9000b57cec5SDimitry Andric   }
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric   bool TestNamedMDs(std::vector<std::string> &NamedMDs);
9030b57cec5SDimitry Andric };
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric 
TestNamedMDs(std::vector<std::string> & NamedMDs)9060b57cec5SDimitry Andric bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric   ValueToValueMapTy VMap;
9090b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   outs() << "Checking for crash with only these named metadata nodes:";
9120b57cec5SDimitry Andric   unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
9130b57cec5SDimitry Andric   for (unsigned i = 0, e = NumPrint; i != e; ++i)
9140b57cec5SDimitry Andric     outs() << " " << NamedMDs[i];
9150b57cec5SDimitry Andric   if (NumPrint < NamedMDs.size())
9160b57cec5SDimitry Andric     outs() << "... <" << NamedMDs.size() << " total>";
9170b57cec5SDimitry Andric   outs() << ": ";
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   // Make a StringMap for faster lookup
9200b57cec5SDimitry Andric   StringSet<> Names;
9210b57cec5SDimitry Andric   for (const std::string &Name : NamedMDs)
9220b57cec5SDimitry Andric     Names.insert(Name);
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   // First collect all the metadata to delete in a vector, then
9250b57cec5SDimitry Andric   // delete them all at once to avoid invalidating the iterator
9260b57cec5SDimitry Andric   std::vector<NamedMDNode *> ToDelete;
9270b57cec5SDimitry Andric   ToDelete.reserve(M->named_metadata_size() - Names.size());
9280b57cec5SDimitry Andric   for (auto &NamedMD : M->named_metadata())
9290b57cec5SDimitry Andric     // Always keep a nonempty llvm.dbg.cu because the Verifier would complain.
9300b57cec5SDimitry Andric     if (!Names.count(NamedMD.getName()) &&
9310b57cec5SDimitry Andric         (!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0)))
9320b57cec5SDimitry Andric       ToDelete.push_back(&NamedMD);
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   for (auto *NamedMD : ToDelete)
9350b57cec5SDimitry Andric     NamedMD->eraseFromParent();
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric   // Verify that this is still valid.
93806c3fb27SDimitry Andric   isValidModule(M, /*ExitOnFailure=*/false);
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   // Try running on the hacked up program...
9410b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
9420b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
9430b57cec5SDimitry Andric     return true;
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric   return false;
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric namespace {
9490b57cec5SDimitry Andric // Reduce the list of operands to named metadata nodes
9500b57cec5SDimitry Andric class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {
9510b57cec5SDimitry Andric   BugDriver &BD;
9520b57cec5SDimitry Andric   BugTester TestFn;
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric public:
ReduceCrashingNamedMDOps(BugDriver & bd,BugTester testFn)9550b57cec5SDimitry Andric   ReduceCrashingNamedMDOps(BugDriver &bd, BugTester testFn)
9560b57cec5SDimitry Andric       : BD(bd), TestFn(testFn) {}
9570b57cec5SDimitry Andric 
doTest(std::vector<const MDNode * > & Prefix,std::vector<const MDNode * > & Kept)9580b57cec5SDimitry Andric   Expected<TestResult> doTest(std::vector<const MDNode *> &Prefix,
9590b57cec5SDimitry Andric                               std::vector<const MDNode *> &Kept) override {
9600b57cec5SDimitry Andric     if (!Kept.empty() && TestNamedMDOps(Kept))
9610b57cec5SDimitry Andric       return KeepSuffix;
9620b57cec5SDimitry Andric     if (!Prefix.empty() && TestNamedMDOps(Prefix))
9630b57cec5SDimitry Andric       return KeepPrefix;
9640b57cec5SDimitry Andric     return NoFailure;
9650b57cec5SDimitry Andric   }
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric   bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps);
9680b57cec5SDimitry Andric };
9690b57cec5SDimitry Andric }
9700b57cec5SDimitry Andric 
TestNamedMDOps(std::vector<const MDNode * > & NamedMDOps)9710b57cec5SDimitry Andric bool ReduceCrashingNamedMDOps::TestNamedMDOps(
9720b57cec5SDimitry Andric     std::vector<const MDNode *> &NamedMDOps) {
9730b57cec5SDimitry Andric   // Convert list to set for fast lookup...
9740b57cec5SDimitry Andric   SmallPtrSet<const MDNode *, 32> OldMDNodeOps;
9750b57cec5SDimitry Andric   for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) {
9760b57cec5SDimitry Andric     OldMDNodeOps.insert(NamedMDOps[i]);
9770b57cec5SDimitry Andric   }
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric   outs() << "Checking for crash with only " << OldMDNodeOps.size();
9800b57cec5SDimitry Andric   if (OldMDNodeOps.size() == 1)
9810b57cec5SDimitry Andric     outs() << " named metadata operand: ";
9820b57cec5SDimitry Andric   else
9830b57cec5SDimitry Andric     outs() << " named metadata operands: ";
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   ValueToValueMapTy VMap;
9860b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric   // This is a little wasteful. In the future it might be good if we could have
9890b57cec5SDimitry Andric   // these dropped during cloning.
9900b57cec5SDimitry Andric   for (auto &NamedMD : BD.getProgram().named_metadata()) {
9910b57cec5SDimitry Andric     // Drop the old one and create a new one
9920b57cec5SDimitry Andric     M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
9930b57cec5SDimitry Andric     NamedMDNode *NewNamedMDNode =
9940b57cec5SDimitry Andric         M->getOrInsertNamedMetadata(NamedMD.getName());
9950b57cec5SDimitry Andric     for (MDNode *op : NamedMD.operands())
9960b57cec5SDimitry Andric       if (OldMDNodeOps.count(op))
9970b57cec5SDimitry Andric         NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap)));
9980b57cec5SDimitry Andric   }
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric   // Verify that this is still valid.
100106c3fb27SDimitry Andric   isValidModule(M, /*ExitOnFailure=*/false);
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   // Try running on the hacked up program...
10040b57cec5SDimitry Andric   if (TestFn(BD, M.get())) {
10050b57cec5SDimitry Andric     // Make sure to use instruction pointers that point into the now-current
10060b57cec5SDimitry Andric     // module, and that they don't include any deleted blocks.
10070b57cec5SDimitry Andric     NamedMDOps.clear();
10080b57cec5SDimitry Andric     for (const MDNode *Node : OldMDNodeOps)
10090b57cec5SDimitry Andric       NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
10120b57cec5SDimitry Andric     return true;
10130b57cec5SDimitry Andric   }
10140b57cec5SDimitry Andric   // It didn't crash, try something else.
10150b57cec5SDimitry Andric   return false;
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric /// Attempt to eliminate as many global initializers as possible.
ReduceGlobalInitializers(BugDriver & BD,BugTester TestFn)10190b57cec5SDimitry Andric static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
10200b57cec5SDimitry Andric   Module &OrigM = BD.getProgram();
10210b57cec5SDimitry Andric   if (OrigM.global_empty())
10220b57cec5SDimitry Andric     return Error::success();
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   // Now try to reduce the number of global variable initializers in the
10250b57cec5SDimitry Andric   // module to something small.
10260b57cec5SDimitry Andric   std::unique_ptr<Module> M = CloneModule(OrigM);
10270b57cec5SDimitry Andric   bool DeletedInit = false;
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   for (GlobalVariable &GV : M->globals()) {
10300b57cec5SDimitry Andric     if (GV.hasInitializer()) {
10310b57cec5SDimitry Andric       DeleteGlobalInitializer(&GV);
10320b57cec5SDimitry Andric       GV.setLinkage(GlobalValue::ExternalLinkage);
10330b57cec5SDimitry Andric       GV.setComdat(nullptr);
10340b57cec5SDimitry Andric       DeletedInit = true;
10350b57cec5SDimitry Andric     }
10360b57cec5SDimitry Andric   }
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   if (!DeletedInit)
10390b57cec5SDimitry Andric     return Error::success();
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   // See if the program still causes a crash...
10420b57cec5SDimitry Andric   outs() << "\nChecking to see if we can delete global inits: ";
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   if (TestFn(BD, M.get())) { // Still crashes?
10450b57cec5SDimitry Andric     BD.setNewProgram(std::move(M));
10460b57cec5SDimitry Andric     outs() << "\n*** Able to remove all global initializers!\n";
10470b57cec5SDimitry Andric     return Error::success();
10480b57cec5SDimitry Andric   }
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   // No longer crashes.
10510b57cec5SDimitry Andric   outs() << "  - Removing all global inits hides problem!\n";
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric   std::vector<GlobalVariable *> GVs;
10540b57cec5SDimitry Andric   for (GlobalVariable &GV : OrigM.globals())
10550b57cec5SDimitry Andric     if (GV.hasInitializer())
10560b57cec5SDimitry Andric       GVs.push_back(&GV);
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric   if (GVs.size() > 1 && !BugpointIsInterrupted) {
10590b57cec5SDimitry Andric     outs() << "\n*** Attempting to reduce the number of global initializers "
10600b57cec5SDimitry Andric            << "in the testcase\n";
10610b57cec5SDimitry Andric 
10620b57cec5SDimitry Andric     unsigned OldSize = GVs.size();
10630b57cec5SDimitry Andric     Expected<bool> Result =
10640b57cec5SDimitry Andric         ReduceCrashingGlobalInitializers(BD, TestFn).reduceList(GVs);
10650b57cec5SDimitry Andric     if (Error E = Result.takeError())
10660b57cec5SDimitry Andric       return E;
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric     if (GVs.size() < OldSize)
10690b57cec5SDimitry Andric       BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");
10700b57cec5SDimitry Andric   }
10710b57cec5SDimitry Andric   return Error::success();
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric 
ReduceInsts(BugDriver & BD,BugTester TestFn)10740b57cec5SDimitry Andric static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
10750b57cec5SDimitry Andric   // Attempt to delete instructions using bisection. This should help out nasty
10760b57cec5SDimitry Andric   // cases with large basic blocks where the problem is at one end.
10770b57cec5SDimitry Andric   if (!BugpointIsInterrupted) {
10780b57cec5SDimitry Andric     std::vector<const Instruction *> Insts;
10790b57cec5SDimitry Andric     for (const Function &F : BD.getProgram())
10800b57cec5SDimitry Andric       for (const BasicBlock &BB : F)
10810b57cec5SDimitry Andric         for (const Instruction &I : BB)
10820b57cec5SDimitry Andric           if (!I.isTerminator())
10830b57cec5SDimitry Andric             Insts.push_back(&I);
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric     Expected<bool> Result =
10860b57cec5SDimitry Andric         ReduceCrashingInstructions(BD, TestFn).reduceList(Insts);
10870b57cec5SDimitry Andric     if (Error E = Result.takeError())
10880b57cec5SDimitry Andric       return E;
10890b57cec5SDimitry Andric   }
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   unsigned Simplification = 2;
10920b57cec5SDimitry Andric   do {
10930b57cec5SDimitry Andric     if (BugpointIsInterrupted)
10940b57cec5SDimitry Andric       // TODO: Should we distinguish this with an "interrupted error"?
10950b57cec5SDimitry Andric       return Error::success();
10960b57cec5SDimitry Andric     --Simplification;
10970b57cec5SDimitry Andric     outs() << "\n*** Attempting to reduce testcase by deleting instruc"
10980b57cec5SDimitry Andric            << "tions: Simplification Level #" << Simplification << '\n';
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric     // Now that we have deleted the functions that are unnecessary for the
11010b57cec5SDimitry Andric     // program, try to remove instructions that are not necessary to cause the
11020b57cec5SDimitry Andric     // crash.  To do this, we loop through all of the instructions in the
11030b57cec5SDimitry Andric     // remaining functions, deleting them (replacing any values produced with
11040b57cec5SDimitry Andric     // nulls), and then running ADCE and SimplifyCFG.  If the transformed input
11050b57cec5SDimitry Andric     // still triggers failure, keep deleting until we cannot trigger failure
11060b57cec5SDimitry Andric     // anymore.
11070b57cec5SDimitry Andric     //
11080b57cec5SDimitry Andric     unsigned InstructionsToSkipBeforeDeleting = 0;
11090b57cec5SDimitry Andric   TryAgain:
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric     // Loop over all of the (non-terminator) instructions remaining in the
11120b57cec5SDimitry Andric     // function, attempting to delete them.
11130b57cec5SDimitry Andric     unsigned CurInstructionNum = 0;
11140b57cec5SDimitry Andric     for (Module::const_iterator FI = BD.getProgram().begin(),
11150b57cec5SDimitry Andric                                 E = BD.getProgram().end();
11160b57cec5SDimitry Andric          FI != E; ++FI)
11170b57cec5SDimitry Andric       if (!FI->isDeclaration())
11180b57cec5SDimitry Andric         for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;
11190b57cec5SDimitry Andric              ++BI)
11200b57cec5SDimitry Andric           for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end();
11210b57cec5SDimitry Andric                I != E; ++I, ++CurInstructionNum) {
11220b57cec5SDimitry Andric             if (InstructionsToSkipBeforeDeleting) {
11230b57cec5SDimitry Andric               --InstructionsToSkipBeforeDeleting;
11240b57cec5SDimitry Andric             } else {
11250b57cec5SDimitry Andric               if (BugpointIsInterrupted)
11260b57cec5SDimitry Andric                 // TODO: Should this be some kind of interrupted error?
11270b57cec5SDimitry Andric                 return Error::success();
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric               if (I->isEHPad() || I->getType()->isTokenTy() ||
11300b57cec5SDimitry Andric                   I->isSwiftError())
11310b57cec5SDimitry Andric                 continue;
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric               outs() << "Checking instruction: " << *I;
11340b57cec5SDimitry Andric               std::unique_ptr<Module> M =
11350b57cec5SDimitry Andric                   BD.deleteInstructionFromProgram(&*I, Simplification);
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric               // Find out if the pass still crashes on this pass...
11380b57cec5SDimitry Andric               if (TestFn(BD, M.get())) {
11390b57cec5SDimitry Andric                 // Yup, it does, we delete the old module, and continue trying
11400b57cec5SDimitry Andric                 // to reduce the testcase...
11410b57cec5SDimitry Andric                 BD.setNewProgram(std::move(M));
11420b57cec5SDimitry Andric                 InstructionsToSkipBeforeDeleting = CurInstructionNum;
11430b57cec5SDimitry Andric                 goto TryAgain; // I wish I had a multi-level break here!
11440b57cec5SDimitry Andric               }
11450b57cec5SDimitry Andric             }
11460b57cec5SDimitry Andric           }
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric     if (InstructionsToSkipBeforeDeleting) {
11490b57cec5SDimitry Andric       InstructionsToSkipBeforeDeleting = 0;
11500b57cec5SDimitry Andric       goto TryAgain;
11510b57cec5SDimitry Andric     }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   } while (Simplification);
1154480093f4SDimitry Andric 
1155480093f4SDimitry Andric   // Attempt to drop metadata from instructions that does not contribute to the
1156480093f4SDimitry Andric   // crash.
1157480093f4SDimitry Andric   if (!BugpointIsInterrupted) {
1158480093f4SDimitry Andric     std::vector<Instruction *> Insts;
1159480093f4SDimitry Andric     for (Function &F : BD.getProgram())
1160480093f4SDimitry Andric       for (Instruction &I : instructions(F))
1161480093f4SDimitry Andric         Insts.push_back(&I);
1162480093f4SDimitry Andric 
1163480093f4SDimitry Andric     Expected<bool> Result =
1164480093f4SDimitry Andric         ReduceCrashingMetadata(BD, TestFn).reduceList(Insts);
1165480093f4SDimitry Andric     if (Error E = Result.takeError())
1166480093f4SDimitry Andric       return E;
1167480093f4SDimitry Andric   }
1168480093f4SDimitry Andric 
11690b57cec5SDimitry Andric   BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");
11700b57cec5SDimitry Andric   return Error::success();
11710b57cec5SDimitry Andric }
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric /// DebugACrash - Given a predicate that determines whether a component crashes
11740b57cec5SDimitry Andric /// on a program, try to destructively reduce the program while still keeping
11750b57cec5SDimitry Andric /// the predicate true.
DebugACrash(BugDriver & BD,BugTester TestFn)11760b57cec5SDimitry Andric static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
11770b57cec5SDimitry Andric   // See if we can get away with nuking some of the global variable initializers
11780b57cec5SDimitry Andric   // in the program...
11790b57cec5SDimitry Andric   if (!NoGlobalRM)
11800b57cec5SDimitry Andric     if (Error E = ReduceGlobalInitializers(BD, TestFn))
11810b57cec5SDimitry Andric       return E;
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric   // Now try to reduce the number of functions in the module to something small.
11840b57cec5SDimitry Andric   std::vector<Function *> Functions;
11850b57cec5SDimitry Andric   for (Function &F : BD.getProgram())
11860b57cec5SDimitry Andric     if (!F.isDeclaration())
11870b57cec5SDimitry Andric       Functions.push_back(&F);
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric   if (Functions.size() > 1 && !BugpointIsInterrupted) {
11900b57cec5SDimitry Andric     outs() << "\n*** Attempting to reduce the number of functions "
11910b57cec5SDimitry Andric               "in the testcase\n";
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric     unsigned OldSize = Functions.size();
11940b57cec5SDimitry Andric     Expected<bool> Result =
11950b57cec5SDimitry Andric         ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);
11960b57cec5SDimitry Andric     if (Error E = Result.takeError())
11970b57cec5SDimitry Andric       return E;
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric     if (Functions.size() < OldSize)
12000b57cec5SDimitry Andric       BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");
12010b57cec5SDimitry Andric   }
12020b57cec5SDimitry Andric 
1203480093f4SDimitry Andric   if (!NoAttributeRM) {
12040b57cec5SDimitry Andric     // For each remaining function, try to reduce that function's attributes.
12050b57cec5SDimitry Andric     std::vector<std::string> FunctionNames;
12060b57cec5SDimitry Andric     for (Function &F : BD.getProgram())
12075ffd83dbSDimitry Andric       FunctionNames.push_back(std::string(F.getName()));
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric     if (!FunctionNames.empty() && !BugpointIsInterrupted) {
1210480093f4SDimitry Andric       outs() << "\n*** Attempting to reduce the number of function attributes"
1211480093f4SDimitry Andric                 " in the testcase\n";
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric       unsigned OldSize = 0;
12140b57cec5SDimitry Andric       unsigned NewSize = 0;
12150b57cec5SDimitry Andric       for (std::string &Name : FunctionNames) {
12160b57cec5SDimitry Andric         Function *Fn = BD.getProgram().getFunction(Name);
1217e8d8bef9SDimitry Andric         assert(Fn && "Could not find function?");
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric         std::vector<Attribute> Attrs;
1220349cc55cSDimitry Andric         for (Attribute A : Fn->getAttributes().getFnAttrs())
12210b57cec5SDimitry Andric           Attrs.push_back(A);
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric         OldSize += Attrs.size();
12240b57cec5SDimitry Andric         Expected<bool> Result =
12250b57cec5SDimitry Andric           ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);
12260b57cec5SDimitry Andric         if (Error E = Result.takeError())
12270b57cec5SDimitry Andric           return E;
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric         NewSize += Attrs.size();
12300b57cec5SDimitry Andric       }
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric       if (OldSize < NewSize)
12330b57cec5SDimitry Andric         BD.EmitProgressBitcode(BD.getProgram(), "reduced-function-attributes");
12340b57cec5SDimitry Andric     }
1235480093f4SDimitry Andric   }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric   // Attempt to change conditional branches into unconditional branches to
12380b57cec5SDimitry Andric   // eliminate blocks.
12390b57cec5SDimitry Andric   if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
12400b57cec5SDimitry Andric     std::vector<const BasicBlock *> Blocks;
12410b57cec5SDimitry Andric     for (Function &F : BD.getProgram())
12420b57cec5SDimitry Andric       for (BasicBlock &BB : F)
12430b57cec5SDimitry Andric         Blocks.push_back(&BB);
12440b57cec5SDimitry Andric     unsigned OldSize = Blocks.size();
12450b57cec5SDimitry Andric     Expected<bool> Result =
12460b57cec5SDimitry Andric         ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks);
12470b57cec5SDimitry Andric     if (Error E = Result.takeError())
12480b57cec5SDimitry Andric       return E;
12490b57cec5SDimitry Andric     Result = ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks);
12500b57cec5SDimitry Andric     if (Error E = Result.takeError())
12510b57cec5SDimitry Andric       return E;
12520b57cec5SDimitry Andric     if (Blocks.size() < OldSize)
12530b57cec5SDimitry Andric       BD.EmitProgressBitcode(BD.getProgram(), "reduced-conditionals");
12540b57cec5SDimitry Andric   }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric   // Attempt to delete entire basic blocks at a time to speed up
12570b57cec5SDimitry Andric   // convergence... this actually works by setting the terminator of the blocks
12580b57cec5SDimitry Andric   // to a return instruction then running simplifycfg, which can potentially
12590b57cec5SDimitry Andric   // shrinks the code dramatically quickly
12600b57cec5SDimitry Andric   //
12610b57cec5SDimitry Andric   if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
12620b57cec5SDimitry Andric     std::vector<const BasicBlock *> Blocks;
12630b57cec5SDimitry Andric     for (Function &F : BD.getProgram())
12640b57cec5SDimitry Andric       for (BasicBlock &BB : F)
12650b57cec5SDimitry Andric         Blocks.push_back(&BB);
12660b57cec5SDimitry Andric     unsigned OldSize = Blocks.size();
12670b57cec5SDimitry Andric     Expected<bool> Result = ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks);
12680b57cec5SDimitry Andric     if (Error E = Result.takeError())
12690b57cec5SDimitry Andric       return E;
12700b57cec5SDimitry Andric     if (Blocks.size() < OldSize)
12710b57cec5SDimitry Andric       BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks");
12720b57cec5SDimitry Andric   }
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric   if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
12750b57cec5SDimitry Andric     std::vector<const BasicBlock *> Blocks;
12760b57cec5SDimitry Andric     for (Function &F : BD.getProgram())
12770b57cec5SDimitry Andric       for (BasicBlock &BB : F)
12780b57cec5SDimitry Andric         Blocks.push_back(&BB);
12790b57cec5SDimitry Andric     unsigned OldSize = Blocks.size();
12800b57cec5SDimitry Andric     Expected<bool> Result = ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks);
12810b57cec5SDimitry Andric     if (Error E = Result.takeError())
12820b57cec5SDimitry Andric       return E;
12830b57cec5SDimitry Andric     if (Blocks.size() < OldSize)
12840b57cec5SDimitry Andric       BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplifycfg");
12850b57cec5SDimitry Andric   }
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric   // Attempt to delete instructions using bisection. This should help out nasty
12880b57cec5SDimitry Andric   // cases with large basic blocks where the problem is at one end.
12890b57cec5SDimitry Andric   if (!BugpointIsInterrupted)
12900b57cec5SDimitry Andric     if (Error E = ReduceInsts(BD, TestFn))
12910b57cec5SDimitry Andric       return E;
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric   // Attempt to strip debug info metadata.
12940b57cec5SDimitry Andric   auto stripMetadata = [&](std::function<bool(Module &)> strip) {
12950b57cec5SDimitry Andric     std::unique_ptr<Module> M = CloneModule(BD.getProgram());
12960b57cec5SDimitry Andric     strip(*M);
12970b57cec5SDimitry Andric     if (TestFn(BD, M.get()))
12980b57cec5SDimitry Andric       BD.setNewProgram(std::move(M));
12990b57cec5SDimitry Andric   };
13000b57cec5SDimitry Andric   if (!NoStripDebugInfo && !BugpointIsInterrupted) {
13010b57cec5SDimitry Andric     outs() << "\n*** Attempting to strip the debug info: ";
13020b57cec5SDimitry Andric     stripMetadata(StripDebugInfo);
13030b57cec5SDimitry Andric   }
13040b57cec5SDimitry Andric   if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {
13050b57cec5SDimitry Andric     outs() << "\n*** Attempting to strip the debug type info: ";
13060b57cec5SDimitry Andric     stripMetadata(stripNonLineTableDebugInfo);
13070b57cec5SDimitry Andric   }
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric   if (!NoNamedMDRM) {
13100b57cec5SDimitry Andric     if (!BugpointIsInterrupted) {
13110b57cec5SDimitry Andric       // Try to reduce the amount of global metadata (particularly debug info),
13120b57cec5SDimitry Andric       // by dropping global named metadata that anchors them
13130b57cec5SDimitry Andric       outs() << "\n*** Attempting to remove named metadata: ";
13140b57cec5SDimitry Andric       std::vector<std::string> NamedMDNames;
13150b57cec5SDimitry Andric       for (auto &NamedMD : BD.getProgram().named_metadata())
13160b57cec5SDimitry Andric         NamedMDNames.push_back(NamedMD.getName().str());
13170b57cec5SDimitry Andric       Expected<bool> Result =
13180b57cec5SDimitry Andric           ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);
13190b57cec5SDimitry Andric       if (Error E = Result.takeError())
13200b57cec5SDimitry Andric         return E;
13210b57cec5SDimitry Andric     }
13220b57cec5SDimitry Andric 
13230b57cec5SDimitry Andric     if (!BugpointIsInterrupted) {
13240b57cec5SDimitry Andric       // Now that we quickly dropped all the named metadata that doesn't
13250b57cec5SDimitry Andric       // contribute to the crash, bisect the operands of the remaining ones
13260b57cec5SDimitry Andric       std::vector<const MDNode *> NamedMDOps;
13270b57cec5SDimitry Andric       for (auto &NamedMD : BD.getProgram().named_metadata())
1328bdd1243dSDimitry Andric         for (auto *op : NamedMD.operands())
13290b57cec5SDimitry Andric           NamedMDOps.push_back(op);
13300b57cec5SDimitry Andric       Expected<bool> Result =
13310b57cec5SDimitry Andric           ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps);
13320b57cec5SDimitry Andric       if (Error E = Result.takeError())
13330b57cec5SDimitry Andric         return E;
13340b57cec5SDimitry Andric     }
13350b57cec5SDimitry Andric     BD.EmitProgressBitcode(BD.getProgram(), "reduced-named-md");
13360b57cec5SDimitry Andric   }
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   // Try to clean up the testcase by running funcresolve and globaldce...
13390b57cec5SDimitry Andric   if (!BugpointIsInterrupted) {
13400b57cec5SDimitry Andric     outs() << "\n*** Attempting to perform final cleanups: ";
13410b57cec5SDimitry Andric     std::unique_ptr<Module> M = CloneModule(BD.getProgram());
13420b57cec5SDimitry Andric     M = BD.performFinalCleanups(std::move(M), true);
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric     // Find out if the pass still crashes on the cleaned up program...
13450b57cec5SDimitry Andric     if (M && TestFn(BD, M.get()))
13460b57cec5SDimitry Andric       BD.setNewProgram(
13470b57cec5SDimitry Andric           std::move(M)); // Yup, it does, keep the reduced version...
13480b57cec5SDimitry Andric   }
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric   BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");
13510b57cec5SDimitry Andric 
13520b57cec5SDimitry Andric   return Error::success();
13530b57cec5SDimitry Andric }
13540b57cec5SDimitry Andric 
TestForOptimizerCrash(const BugDriver & BD,Module * M)13550b57cec5SDimitry Andric static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {
13560b57cec5SDimitry Andric   return BD.runPasses(*M, BD.getPassesToRun());
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric /// debugOptimizerCrash - This method is called when some pass crashes on input.
13600b57cec5SDimitry Andric /// It attempts to prune down the testcase to something reasonable, and figure
13610b57cec5SDimitry Andric /// out exactly which pass is crashing.
13620b57cec5SDimitry Andric ///
debugOptimizerCrash(const std::string & ID)13630b57cec5SDimitry Andric Error BugDriver::debugOptimizerCrash(const std::string &ID) {
13640b57cec5SDimitry Andric   outs() << "\n*** Debugging optimizer crash!\n";
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric   // Reduce the list of passes which causes the optimizer to crash...
13670b57cec5SDimitry Andric   if (!BugpointIsInterrupted && !DontReducePassList) {
13680b57cec5SDimitry Andric     Expected<bool> Result = ReducePassList(*this).reduceList(PassesToRun);
13690b57cec5SDimitry Andric     if (Error E = Result.takeError())
13700b57cec5SDimitry Andric       return E;
13710b57cec5SDimitry Andric   }
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric   outs() << "\n*** Found crashing pass"
13740b57cec5SDimitry Andric          << (PassesToRun.size() == 1 ? ": " : "es: ")
13750b57cec5SDimitry Andric          << getPassesString(PassesToRun) << '\n';
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric   EmitProgressBitcode(*Program, ID);
13780b57cec5SDimitry Andric 
1379480093f4SDimitry Andric   auto Res = DebugACrash(*this, TestForOptimizerCrash);
1380480093f4SDimitry Andric   if (Res || DontReducePassList)
1381480093f4SDimitry Andric     return Res;
1382480093f4SDimitry Andric   // Try to reduce the pass list again. This covers additional cases
1383480093f4SDimitry Andric   // we failed to reduce earlier, because of more complex pass dependencies
1384480093f4SDimitry Andric   // triggering the crash.
1385480093f4SDimitry Andric   auto SecondRes = ReducePassList(*this).reduceList(PassesToRun);
1386480093f4SDimitry Andric   if (Error E = SecondRes.takeError())
1387480093f4SDimitry Andric     return E;
1388480093f4SDimitry Andric   outs() << "\n*** Found crashing pass"
1389480093f4SDimitry Andric          << (PassesToRun.size() == 1 ? ": " : "es: ")
1390480093f4SDimitry Andric          << getPassesString(PassesToRun) << '\n';
1391480093f4SDimitry Andric 
1392480093f4SDimitry Andric   EmitProgressBitcode(getProgram(), "reduced-simplified");
1393480093f4SDimitry Andric   return Res;
13940b57cec5SDimitry Andric }
13950b57cec5SDimitry Andric 
TestForCodeGenCrash(const BugDriver & BD,Module * M)13960b57cec5SDimitry Andric static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
13970b57cec5SDimitry Andric   if (Error E = BD.compileProgram(*M)) {
13980b57cec5SDimitry Andric     if (VerboseErrors)
13990b57cec5SDimitry Andric       errs() << toString(std::move(E)) << "\n";
14000b57cec5SDimitry Andric     else {
14010b57cec5SDimitry Andric       consumeError(std::move(E));
14020b57cec5SDimitry Andric       errs() << "<crash>\n";
14030b57cec5SDimitry Andric     }
14040b57cec5SDimitry Andric     return true; // Tool is still crashing.
14050b57cec5SDimitry Andric   }
14060b57cec5SDimitry Andric   errs() << '\n';
14070b57cec5SDimitry Andric   return false;
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric /// debugCodeGeneratorCrash - This method is called when the code generator
14110b57cec5SDimitry Andric /// crashes on an input.  It attempts to reduce the input as much as possible
14120b57cec5SDimitry Andric /// while still causing the code generator to crash.
debugCodeGeneratorCrash()14130b57cec5SDimitry Andric Error BugDriver::debugCodeGeneratorCrash() {
14140b57cec5SDimitry Andric   errs() << "*** Debugging code generator crash!\n";
14150b57cec5SDimitry Andric 
14160b57cec5SDimitry Andric   return DebugACrash(*this, TestForCodeGenCrash);
14170b57cec5SDimitry Andric }
1418