173a6bdd9SChris Lattner //===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
273a6bdd9SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609344dcfSJohn Criswell //
709344dcfSJohn Criswell //===----------------------------------------------------------------------===//
809344dcfSJohn Criswell //
973a6bdd9SChris Lattner // This file defines the bugpoint internals that narrow down compilation crashes
1073a6bdd9SChris Lattner //
1173a6bdd9SChris Lattner //===----------------------------------------------------------------------===//
1273a6bdd9SChris Lattner 
1373a6bdd9SChris Lattner #include "BugDriver.h"
141d080f24SChris Lattner #include "ListReducer.h"
154d88a1c2SChandler Carruth #include "ToolRunner.h"
164d88a1c2SChandler Carruth #include "llvm/ADT/SmallPtrSet.h"
1734ca831dSKeno Fischer #include "llvm/ADT/StringSet.h"
188d0a0811SJustin Bogner #include "llvm/Analysis/TargetTransformInfo.h"
191305dc33SChandler Carruth #include "llvm/IR/CFG.h"
209fb823bbSChandler Carruth #include "llvm/IR/Constants.h"
21e5428043SMichael Ilseman #include "llvm/IR/DebugInfo.h"
229fb823bbSChandler Carruth #include "llvm/IR/DerivedTypes.h"
2329e8b8ceSFlorian Hahn #include "llvm/IR/InstIterator.h"
249fb823bbSChandler Carruth #include "llvm/IR/Instructions.h"
2530d69c2eSChandler Carruth #include "llvm/IR/LegacyPassManager.h"
269fb823bbSChandler Carruth #include "llvm/IR/Module.h"
279fb823bbSChandler Carruth #include "llvm/IR/ValueSymbolTable.h"
285ad5f15cSChandler Carruth #include "llvm/IR/Verifier.h"
290c2305b1SMisha Brukman #include "llvm/Pass.h"
304d88a1c2SChandler Carruth #include "llvm/Support/CommandLine.h"
314d88a1c2SChandler Carruth #include "llvm/Support/FileUtilities.h"
32f32939bbSChris Lattner #include "llvm/Transforms/Scalar.h"
33271ca401SDaniel Berlin #include "llvm/Transforms/Utils/BasicBlockUtils.h"
341d080f24SChris Lattner #include "llvm/Transforms/Utils/Cloning.h"
3529e8b8ceSFlorian Hahn #include "llvm/Transforms/Utils/Local.h"
361d080f24SChris Lattner #include <set>
372f1aa118SChris Lattner using namespace llvm;
3873a6bdd9SChris Lattner 
39ef9aa129SAndrew Lenharth namespace {
408d0a0811SJustin Bogner cl::opt<bool> KeepMain("keep-main",
41ef9aa129SAndrew Lenharth                        cl::desc("Force function reduction to keep main"),
42ef9aa129SAndrew Lenharth                        cl::init(false));
438d0a0811SJustin Bogner cl::opt<bool> NoGlobalRM("disable-global-remove",
445bd3f7b4STorok Edwin                          cl::desc("Do not remove global variables"),
455bd3f7b4STorok Edwin                          cl::init(false));
46f87e20ddSJF Bastien 
476f06eda0SMatt Arsenault cl::opt<bool> NoAttributeRM("disable-attribute-remove",
486f06eda0SMatt Arsenault                          cl::desc("Do not remove function attributes"),
496f06eda0SMatt Arsenault                          cl::init(false));
506f06eda0SMatt Arsenault 
518d0a0811SJustin Bogner cl::opt<bool> ReplaceFuncsWithNull(
528d0a0811SJustin Bogner     "replace-funcs-with-null",
53f87e20ddSJF Bastien     cl::desc("When stubbing functions, replace all uses will null"),
54f87e20ddSJF Bastien     cl::init(false));
558d0a0811SJustin Bogner cl::opt<bool> DontReducePassList("disable-pass-list-reduction",
56f87e20ddSJF Bastien                                  cl::desc("Skip pass list reduction steps"),
57f87e20ddSJF Bastien                                  cl::init(false));
5834ca831dSKeno Fischer 
5934ca831dSKeno Fischer cl::opt<bool> NoNamedMDRM("disable-namedmd-remove",
6034ca831dSKeno Fischer                           cl::desc("Do not remove global named metadata"),
6134ca831dSKeno Fischer                           cl::init(false));
62e5428043SMichael Ilseman cl::opt<bool> NoStripDebugInfo("disable-strip-debuginfo",
63e5428043SMichael Ilseman                                cl::desc("Do not strip debug info metadata"),
64e5428043SMichael Ilseman                                cl::init(false));
65e5428043SMichael Ilseman cl::opt<bool> NoStripDebugTypeInfo("disable-strip-debug-types",
66e5428043SMichael Ilseman                                cl::desc("Do not strip debug type info metadata"),
67e5428043SMichael Ilseman                                cl::init(false));
688f7d0199SSebastian Pop cl::opt<bool> VerboseErrors("verbose-errors",
698f7d0199SSebastian Pop                             cl::desc("Print the output of crashing program"),
708f7d0199SSebastian Pop                             cl::init(false));
71ef9aa129SAndrew Lenharth }
72ef9aa129SAndrew Lenharth 
73960707c3SBrian Gaeke namespace llvm {
7433e81a82SRafael Espindola class ReducePassList : public ListReducer<std::string> {
7516a41310SChris Lattner   BugDriver &BD;
768d0a0811SJustin Bogner 
7716a41310SChris Lattner public:
ReducePassList(BugDriver & bd)78327019b4SChris Lattner   ReducePassList(BugDriver &bd) : BD(bd) {}
7916a41310SChris Lattner 
801c039155SJustin Bogner   // Return true iff running the "removed" passes succeeds, and running the
811c039155SJustin Bogner   // "Kept" passes fail when run on the output of the "removed" passes.  If we
821c039155SJustin Bogner   // return true, we update the current module of bugpoint.
831c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<std::string> &Removed,
841c039155SJustin Bogner                               std::vector<std::string> &Kept) override;
8516a41310SChris Lattner };
862f1aa118SChris Lattner }
871d080f24SChris Lattner 
881c039155SJustin Bogner Expected<ReducePassList::TestResult>
doTest(std::vector<std::string> & Prefix,std::vector<std::string> & Suffix)8933e81a82SRafael Espindola ReducePassList::doTest(std::vector<std::string> &Prefix,
901c039155SJustin Bogner                        std::vector<std::string> &Suffix) {
91bb876654SRafael Espindola   std::string PrefixOutput;
922c8bcab6SRafael Espindola   std::unique_ptr<Module> OrigProgram;
931d080f24SChris Lattner   if (!Prefix.empty()) {
94ee05152cSDan Gohman     outs() << "Checking to see if these passes crash: "
951d080f24SChris Lattner            << getPassesString(Prefix) << ": ";
96bb876654SRafael Espindola     if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))
971d080f24SChris Lattner       return KeepPrefix;
981d080f24SChris Lattner 
99f6074ed9SRafael Espindola     OrigProgram = std::move(BD.Program);
100a9656314SChris Lattner 
101f6074ed9SRafael Espindola     BD.Program = parseInputFile(PrefixOutput, BD.getContext());
102e6cb63e4SCraig Topper     if (BD.Program == nullptr) {
103d8db3760SDan Gohman       errs() << BD.getToolName() << ": Error reading bitcode file '"
104bb876654SRafael Espindola              << PrefixOutput << "'!\n";
1051d080f24SChris Lattner       exit(1);
1061d080f24SChris Lattner     }
107bb876654SRafael Espindola     sys::fs::remove(PrefixOutput);
108a9656314SChris Lattner   }
109a9656314SChris Lattner 
1108d0a0811SJustin Bogner   outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)
1118d0a0811SJustin Bogner          << ": ";
1121d080f24SChris Lattner 
1132c8bcab6SRafael Espindola   if (BD.runPasses(BD.getProgram(), Suffix))
1142c8bcab6SRafael Espindola     return KeepSuffix; // The suffix crashes alone...
1151d080f24SChris Lattner 
1161d080f24SChris Lattner   // Nothing failed, restore state...
117f6074ed9SRafael Espindola   if (OrigProgram)
118f6074ed9SRafael Espindola     BD.Program = std::move(OrigProgram);
1191d080f24SChris Lattner   return NoFailure;
1201d080f24SChris Lattner }
1211d080f24SChris Lattner 
12208d829daSVedant Kumar using BugTester = bool (*)(const BugDriver &, Module *);
12308d829daSVedant Kumar 
1243f83343cSBill Wendling namespace {
12566e85e6cSVedant Kumar /// ReduceCrashingGlobalInitializers - This works by removing global variable
12666e85e6cSVedant Kumar /// initializers and seeing if the program still crashes. If it does, then we
12766e85e6cSVedant Kumar /// keep that program and try again.
12866e85e6cSVedant Kumar class ReduceCrashingGlobalInitializers : public ListReducer<GlobalVariable *> {
1293f83343cSBill Wendling   BugDriver &BD;
13008d829daSVedant Kumar   BugTester TestFn;
1318d0a0811SJustin Bogner 
1323f83343cSBill Wendling public:
ReduceCrashingGlobalInitializers(BugDriver & bd,BugTester testFn)13366e85e6cSVedant Kumar   ReduceCrashingGlobalInitializers(BugDriver &bd, BugTester testFn)
1343f83343cSBill Wendling       : BD(bd), TestFn(testFn) {}
1353f83343cSBill Wendling 
doTest(std::vector<GlobalVariable * > & Prefix,std::vector<GlobalVariable * > & Kept)1361c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<GlobalVariable *> &Prefix,
1371c039155SJustin Bogner                               std::vector<GlobalVariable *> &Kept) override {
1383f83343cSBill Wendling     if (!Kept.empty() && TestGlobalVariables(Kept))
1393f83343cSBill Wendling       return KeepSuffix;
1403f83343cSBill Wendling     if (!Prefix.empty() && TestGlobalVariables(Prefix))
1413f83343cSBill Wendling       return KeepPrefix;
1423f83343cSBill Wendling     return NoFailure;
1433f83343cSBill Wendling   }
1443f83343cSBill Wendling 
1453f83343cSBill Wendling   bool TestGlobalVariables(std::vector<GlobalVariable *> &GVs);
1463f83343cSBill Wendling };
1473f83343cSBill Wendling }
1483f83343cSBill Wendling 
TestGlobalVariables(std::vector<GlobalVariable * > & GVs)14966e85e6cSVedant Kumar bool ReduceCrashingGlobalInitializers::TestGlobalVariables(
1503f83343cSBill Wendling     std::vector<GlobalVariable *> &GVs) {
1513f83343cSBill Wendling   // Clone the program to try hacking it apart...
152229e38f0SRafael Espindola   ValueToValueMapTy VMap;
153f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
1543f83343cSBill Wendling 
1553f83343cSBill Wendling   // Convert list to set for fast lookup...
1563f83343cSBill Wendling   std::set<GlobalVariable *> GVSet;
1573f83343cSBill Wendling 
1583f83343cSBill Wendling   for (unsigned i = 0, e = GVs.size(); i != e; ++i) {
1590dc3c2d3SDevang Patel     GlobalVariable *CMGV = cast<GlobalVariable>(VMap[GVs[i]]);
1603f83343cSBill Wendling     assert(CMGV && "Global Variable not in module?!");
1613f83343cSBill Wendling     GVSet.insert(CMGV);
1623f83343cSBill Wendling   }
1633f83343cSBill Wendling 
164ee05152cSDan Gohman   outs() << "Checking for crash with only these global variables: ";
1653f83343cSBill Wendling   PrintGlobalVariableList(GVs);
166ee05152cSDan Gohman   outs() << ": ";
1673f83343cSBill Wendling 
1683f83343cSBill Wendling   // Loop over and delete any global variables which we aren't supposed to be
1693f83343cSBill Wendling   // playing with...
170306d16e0SDuncan P. N. Exon Smith   for (GlobalVariable &I : M->globals())
171306d16e0SDuncan P. N. Exon Smith     if (I.hasInitializer() && !GVSet.count(&I)) {
17228ad2b47SHal Finkel       DeleteGlobalInitializer(&I);
173306d16e0SDuncan P. N. Exon Smith       I.setLinkage(GlobalValue::ExternalLinkage);
1742a445cf7SJustin Lebar       I.setComdat(nullptr);
1753f83343cSBill Wendling     }
1763f83343cSBill Wendling 
1773f83343cSBill Wendling   // Try running the hacked up program...
17866e85e6cSVedant Kumar   if (TestFn(BD, M.get())) {
179f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
1803f83343cSBill Wendling 
1813f83343cSBill Wendling     // Make sure to use global variable pointers that point into the now-current
1823f83343cSBill Wendling     // module.
1833f83343cSBill Wendling     GVs.assign(GVSet.begin(), GVSet.end());
1843f83343cSBill Wendling     return true;
1853f83343cSBill Wendling   }
1863f83343cSBill Wendling 
1873f83343cSBill Wendling   return false;
1883f83343cSBill Wendling }
1893f83343cSBill Wendling 
190a379b181SDavid Blaikie namespace {
1913f83343cSBill Wendling /// ReduceCrashingFunctions reducer - This works by removing functions and
1923f83343cSBill Wendling /// seeing if the program still crashes. If it does, then keep the newer,
1933f83343cSBill Wendling /// smaller program.
1943f83343cSBill Wendling ///
195fd72bed3SChris Lattner class ReduceCrashingFunctions : public ListReducer<Function *> {
1961d080f24SChris Lattner   BugDriver &BD;
19708d829daSVedant Kumar   BugTester TestFn;
1988d0a0811SJustin Bogner 
1991d080f24SChris Lattner public:
ReduceCrashingFunctions(BugDriver & bd,BugTester testFn)20008d829daSVedant Kumar   ReduceCrashingFunctions(BugDriver &bd, BugTester testFn)
2018bda4c49SChris Lattner       : BD(bd), TestFn(testFn) {}
2021d080f24SChris Lattner 
doTest(std::vector<Function * > & Prefix,std::vector<Function * > & Kept)2031c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<Function *> &Prefix,
2041c039155SJustin Bogner                               std::vector<Function *> &Kept) override {
205689398feSMisha Brukman     if (!Kept.empty() && TestFuncs(Kept))
2061d080f24SChris Lattner       return KeepSuffix;
2071d080f24SChris Lattner     if (!Prefix.empty() && TestFuncs(Prefix))
2081d080f24SChris Lattner       return KeepPrefix;
2091d080f24SChris Lattner     return NoFailure;
2101d080f24SChris Lattner   }
2111d080f24SChris Lattner 
212fd72bed3SChris Lattner   bool TestFuncs(std::vector<Function *> &Prefix);
2131d080f24SChris Lattner };
2142f1aa118SChris Lattner }
2151d080f24SChris Lattner 
RemoveFunctionReferences(Module * M,const char * Name)216f87e20ddSJF Bastien static void RemoveFunctionReferences(Module *M, const char *Name) {
217f87e20ddSJF Bastien   auto *UsedVar = M->getGlobalVariable(Name, true);
2188d0a0811SJustin Bogner   if (!UsedVar || !UsedVar->hasInitializer())
2198d0a0811SJustin Bogner     return;
220f87e20ddSJF Bastien   if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) {
221f87e20ddSJF Bastien     assert(UsedVar->use_empty());
222f87e20ddSJF Bastien     UsedVar->eraseFromParent();
223f87e20ddSJF Bastien     return;
224f87e20ddSJF Bastien   }
225f87e20ddSJF Bastien   auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer());
226f87e20ddSJF Bastien   std::vector<Constant *> Used;
227f87e20ddSJF Bastien   for (Value *V : OldUsedVal->operand_values()) {
228f87e20ddSJF Bastien     Constant *Op = cast<Constant>(V->stripPointerCasts());
229f87e20ddSJF Bastien     if (!Op->isNullValue()) {
230f87e20ddSJF Bastien       Used.push_back(cast<Constant>(V));
231f87e20ddSJF Bastien     }
232f87e20ddSJF Bastien   }
233f87e20ddSJF Bastien   auto *NewValElemTy = OldUsedVal->getType()->getElementType();
234f87e20ddSJF Bastien   auto *NewValTy = ArrayType::get(NewValElemTy, Used.size());
235f87e20ddSJF Bastien   auto *NewUsedVal = ConstantArray::get(NewValTy, Used);
236f87e20ddSJF Bastien   UsedVar->mutateType(NewUsedVal->getType()->getPointerTo());
237f87e20ddSJF Bastien   UsedVar->setInitializer(NewUsedVal);
238f87e20ddSJF Bastien }
239f87e20ddSJF Bastien 
TestFuncs(std::vector<Function * > & Funcs)240fd72bed3SChris Lattner bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
2416e0520e9SDmitri Gribenko   // If main isn't present, claim there is no problem.
242f6074ed9SRafael Espindola   if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))
243ef9aa129SAndrew Lenharth     return false;
244ef9aa129SAndrew Lenharth 
2458b2bd4edSMisha Brukman   // Clone the program to try hacking it apart...
246229e38f0SRafael Espindola   ValueToValueMapTy VMap;
247f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
2481d080f24SChris Lattner 
2491d080f24SChris Lattner   // Convert list to set for fast lookup...
2501d080f24SChris Lattner   std::set<Function *> Functions;
2511d080f24SChris Lattner   for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
2520dc3c2d3SDevang Patel     Function *CMF = cast<Function>(VMap[Funcs[i]]);
2531d080f24SChris Lattner     assert(CMF && "Function not in module?!");
2543aaaa0b2SReid Spencer     assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty");
255bcad718fSDan Gohman     assert(CMF->getName() == Funcs[i]->getName() && "wrong name");
2561d080f24SChris Lattner     Functions.insert(CMF);
2571d080f24SChris Lattner   }
2581d080f24SChris Lattner 
259ee05152cSDan Gohman   outs() << "Checking for crash with only these functions: ";
260fd72bed3SChris Lattner   PrintFunctionList(Funcs);
261ee05152cSDan Gohman   outs() << ": ";
262f87e20ddSJF Bastien   if (!ReplaceFuncsWithNull) {
2631d080f24SChris Lattner     // Loop over and delete any functions which we aren't supposed to be playing
2641d080f24SChris Lattner     // with...
265306d16e0SDuncan P. N. Exon Smith     for (Function &I : *M)
266306d16e0SDuncan P. N. Exon Smith       if (!I.isDeclaration() && !Functions.count(&I))
267306d16e0SDuncan P. N. Exon Smith         DeleteFunctionBody(&I);
268f87e20ddSJF Bastien   } else {
269f87e20ddSJF Bastien     std::vector<GlobalValue *> ToRemove;
270f87e20ddSJF Bastien     // First, remove aliases to functions we're about to purge.
271f87e20ddSJF Bastien     for (GlobalAlias &Alias : M->aliases()) {
27240ec1c0fSItay Bookstein       GlobalObject *Root = Alias.getAliaseeObject();
273*46f0e2ceSSimon Pilgrim       auto *F = dyn_cast<Function>(Root);
274f87e20ddSJF Bastien       if (F) {
275f87e20ddSJF Bastien         if (Functions.count(F))
276f87e20ddSJF Bastien           // We're keeping this function.
277f87e20ddSJF Bastien           continue;
278f87e20ddSJF Bastien       } else if (Root->isNullValue()) {
279f87e20ddSJF Bastien         // This referenced a globalalias that we've already replaced,
280f87e20ddSJF Bastien         // so we still need to replace this alias.
281*46f0e2ceSSimon Pilgrim       } else {
282f87e20ddSJF Bastien         // Not a function, therefore not something we mess with.
283f87e20ddSJF Bastien         continue;
284f87e20ddSJF Bastien       }
2851d080f24SChris Lattner 
286f87e20ddSJF Bastien       PointerType *Ty = cast<PointerType>(Alias.getType());
287f87e20ddSJF Bastien       Constant *Replacement = ConstantPointerNull::get(Ty);
288f87e20ddSJF Bastien       Alias.replaceAllUsesWith(Replacement);
289f87e20ddSJF Bastien       ToRemove.push_back(&Alias);
290f87e20ddSJF Bastien     }
291f87e20ddSJF Bastien 
292306d16e0SDuncan P. N. Exon Smith     for (Function &I : *M) {
293306d16e0SDuncan P. N. Exon Smith       if (!I.isDeclaration() && !Functions.count(&I)) {
294306d16e0SDuncan P. N. Exon Smith         PointerType *Ty = cast<PointerType>(I.getType());
295f87e20ddSJF Bastien         Constant *Replacement = ConstantPointerNull::get(Ty);
296306d16e0SDuncan P. N. Exon Smith         I.replaceAllUsesWith(Replacement);
297306d16e0SDuncan P. N. Exon Smith         ToRemove.push_back(&I);
298f87e20ddSJF Bastien       }
299f87e20ddSJF Bastien     }
300f87e20ddSJF Bastien 
301f87e20ddSJF Bastien     for (auto *F : ToRemove) {
302f87e20ddSJF Bastien       F->eraseFromParent();
303f87e20ddSJF Bastien     }
304f87e20ddSJF Bastien 
305f87e20ddSJF Bastien     // Finally, remove any null members from any global intrinsic.
30615647b77SRafael Espindola     RemoveFunctionReferences(M.get(), "llvm.used");
30715647b77SRafael Espindola     RemoveFunctionReferences(M.get(), "llvm.compiler.used");
308f87e20ddSJF Bastien   }
3091d080f24SChris Lattner   // Try running the hacked up program...
31015647b77SRafael Espindola   if (TestFn(BD, M.get())) {
311f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
3121d080f24SChris Lattner 
3131d080f24SChris Lattner     // Make sure to use function pointers that point into the now-current
3141d080f24SChris Lattner     // module.
3151d080f24SChris Lattner     Funcs.assign(Functions.begin(), Functions.end());
3161d080f24SChris Lattner     return true;
3171d080f24SChris Lattner   }
3181d080f24SChris Lattner   return false;
3191d080f24SChris Lattner }
3201d080f24SChris Lattner 
3211942f98dSChris Lattner namespace {
322274981ebSBrian Gesiak /// ReduceCrashingFunctionAttributes reducer - This works by removing
323274981ebSBrian Gesiak /// attributes on a particular function and seeing if the program still crashes.
324274981ebSBrian Gesiak /// If it does, then keep the newer, smaller program.
325274981ebSBrian Gesiak ///
326274981ebSBrian Gesiak class ReduceCrashingFunctionAttributes : public ListReducer<Attribute> {
327274981ebSBrian Gesiak   BugDriver &BD;
328274981ebSBrian Gesiak   std::string FnName;
329274981ebSBrian Gesiak   BugTester TestFn;
330274981ebSBrian Gesiak 
331274981ebSBrian Gesiak public:
ReduceCrashingFunctionAttributes(BugDriver & bd,const std::string & FnName,BugTester testFn)332274981ebSBrian Gesiak   ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,
333274981ebSBrian Gesiak                                    BugTester testFn)
334274981ebSBrian Gesiak       : BD(bd), FnName(FnName), TestFn(testFn) {}
335274981ebSBrian Gesiak 
doTest(std::vector<Attribute> & Prefix,std::vector<Attribute> & Kept)336274981ebSBrian Gesiak   Expected<TestResult> doTest(std::vector<Attribute> &Prefix,
337274981ebSBrian Gesiak                               std::vector<Attribute> &Kept) override {
338274981ebSBrian Gesiak     if (!Kept.empty() && TestFuncAttrs(Kept))
339274981ebSBrian Gesiak       return KeepSuffix;
340274981ebSBrian Gesiak     if (!Prefix.empty() && TestFuncAttrs(Prefix))
341274981ebSBrian Gesiak       return KeepPrefix;
342274981ebSBrian Gesiak     return NoFailure;
343274981ebSBrian Gesiak   }
344274981ebSBrian Gesiak 
345274981ebSBrian Gesiak   bool TestFuncAttrs(std::vector<Attribute> &Attrs);
346274981ebSBrian Gesiak };
347274981ebSBrian Gesiak }
348274981ebSBrian Gesiak 
TestFuncAttrs(std::vector<Attribute> & Attrs)349274981ebSBrian Gesiak bool ReduceCrashingFunctionAttributes::TestFuncAttrs(
350274981ebSBrian Gesiak     std::vector<Attribute> &Attrs) {
351274981ebSBrian Gesiak   // Clone the program to try hacking it apart...
352274981ebSBrian Gesiak   std::unique_ptr<Module> M = CloneModule(BD.getProgram());
353274981ebSBrian Gesiak   Function *F = M->getFunction(FnName);
354274981ebSBrian Gesiak 
355274981ebSBrian Gesiak   // Build up an AttributeList from the attributes we've been given by the
356274981ebSBrian Gesiak   // reducer.
357d2cc6c2dSSerge Guelton   AttrBuilder AB(M->getContext());
358274981ebSBrian Gesiak   for (auto A : Attrs)
359274981ebSBrian Gesiak     AB.addAttribute(A);
360274981ebSBrian Gesiak   AttributeList NewAttrs;
361de0ae9e8SArthur Eubanks   NewAttrs = NewAttrs.addFnAttributes(BD.getContext(), AB);
362274981ebSBrian Gesiak 
363274981ebSBrian Gesiak   // Set this new list of attributes on the function.
364274981ebSBrian Gesiak   F->setAttributes(NewAttrs);
365274981ebSBrian Gesiak 
366055aeb52SDavid Greene   // If the attribute list includes "optnone" we need to make sure it also
367055aeb52SDavid Greene   // includes "noinline" otherwise we will get a verifier failure.
368055aeb52SDavid Greene   if (F->hasFnAttribute(Attribute::OptimizeNone))
369055aeb52SDavid Greene     F->addFnAttr(Attribute::NoInline);
370055aeb52SDavid Greene 
371274981ebSBrian Gesiak   // Try running on the hacked up program...
372274981ebSBrian Gesiak   if (TestFn(BD, M.get())) {
373274981ebSBrian Gesiak     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
374274981ebSBrian Gesiak 
375274981ebSBrian Gesiak     // Pass along the set of attributes that caused the crash.
376274981ebSBrian Gesiak     Attrs.clear();
37780ea2bb5SArthur Eubanks     for (Attribute A : NewAttrs.getFnAttrs()) {
378274981ebSBrian Gesiak       Attrs.push_back(A);
379274981ebSBrian Gesiak     }
380274981ebSBrian Gesiak     return true;
381274981ebSBrian Gesiak   }
382274981ebSBrian Gesiak   return false;
383274981ebSBrian Gesiak }
384274981ebSBrian Gesiak 
385274981ebSBrian Gesiak namespace {
38660606266SDaniel Berlin /// Simplify the CFG without completely destroying it.
38760606266SDaniel Berlin /// This is not well defined, but basically comes down to "try to eliminate
38860606266SDaniel Berlin /// unreachable blocks and constant fold terminators without deciding that
38960606266SDaniel Berlin /// certain undefined behavior cuts off the program at the legs".
simpleSimplifyCfg(Function & F,SmallVectorImpl<BasicBlock * > & BBs)39060606266SDaniel Berlin void simpleSimplifyCfg(Function &F, SmallVectorImpl<BasicBlock *> &BBs) {
39160606266SDaniel Berlin   if (F.empty())
39260606266SDaniel Berlin     return;
39360606266SDaniel Berlin 
39460606266SDaniel Berlin   for (auto *BB : BBs) {
39560606266SDaniel Berlin     ConstantFoldTerminator(BB);
39660606266SDaniel Berlin     MergeBlockIntoPredecessor(BB);
39760606266SDaniel Berlin   }
39860606266SDaniel Berlin 
39960606266SDaniel Berlin   // Remove unreachable blocks
40060606266SDaniel Berlin   // removeUnreachableBlocks can't be used here, it will turn various
40160606266SDaniel Berlin   // undefined behavior into unreachables, but bugpoint was the thing that
40260606266SDaniel Berlin   // generated the undefined behavior, and we don't want it to kill the entire
40360606266SDaniel Berlin   // program.
40460606266SDaniel Berlin   SmallPtrSet<BasicBlock *, 16> Visited;
40560606266SDaniel Berlin   for (auto *BB : depth_first(&F.getEntryBlock()))
40660606266SDaniel Berlin     Visited.insert(BB);
40760606266SDaniel Berlin 
40860606266SDaniel Berlin   SmallVector<BasicBlock *, 16> Unreachable;
40960606266SDaniel Berlin   for (auto &BB : F)
41060606266SDaniel Berlin     if (!Visited.count(&BB))
41160606266SDaniel Berlin       Unreachable.push_back(&BB);
41260606266SDaniel Berlin 
41360606266SDaniel Berlin   // The dead BB's may be in a dead cycle or otherwise have references to each
41460606266SDaniel Berlin   // other.  Because of this, we have to drop all references first, then delete
41560606266SDaniel Berlin   // them all at once.
41660606266SDaniel Berlin   for (auto *BB : Unreachable) {
41760606266SDaniel Berlin     for (BasicBlock *Successor : successors(&*BB))
41860606266SDaniel Berlin       if (Visited.count(Successor))
41960606266SDaniel Berlin         Successor->removePredecessor(&*BB);
42060606266SDaniel Berlin     BB->dropAllReferences();
42160606266SDaniel Berlin   }
42260606266SDaniel Berlin   for (auto *BB : Unreachable)
42360606266SDaniel Berlin     BB->eraseFromParent();
42460606266SDaniel Berlin }
4252f1aa118SChris Lattner /// ReduceCrashingBlocks reducer - This works by setting the terminators of
4262f1aa118SChris Lattner /// all terminators except the specified basic blocks to a 'ret' instruction,
427472462c4SBjorn Pettersson /// then running the simplifycfg pass.  This has the effect of chopping up
4282f1aa118SChris Lattner /// the CFG really fast which can reduce large functions quickly.
429f32939bbSChris Lattner ///
4308bda4c49SChris Lattner class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {
431f32939bbSChris Lattner   BugDriver &BD;
43208d829daSVedant Kumar   BugTester TestFn;
4338d0a0811SJustin Bogner 
434f32939bbSChris Lattner public:
ReduceCrashingBlocks(BugDriver & BD,BugTester testFn)43508d829daSVedant Kumar   ReduceCrashingBlocks(BugDriver &BD, BugTester testFn)
43660606266SDaniel Berlin       : BD(BD), TestFn(testFn) {}
437f32939bbSChris Lattner 
doTest(std::vector<const BasicBlock * > & Prefix,std::vector<const BasicBlock * > & Kept)4381c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
4391c039155SJustin Bogner                               std::vector<const BasicBlock *> &Kept) override {
440fe69bc50SJohn Criswell     if (!Kept.empty() && TestBlocks(Kept))
441f32939bbSChris Lattner       return KeepSuffix;
442f32939bbSChris Lattner     if (!Prefix.empty() && TestBlocks(Prefix))
443f32939bbSChris Lattner       return KeepPrefix;
444f32939bbSChris Lattner     return NoFailure;
445f32939bbSChris Lattner   }
446f32939bbSChris Lattner 
4478bda4c49SChris Lattner   bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
448f32939bbSChris Lattner };
4492f1aa118SChris Lattner }
450f32939bbSChris Lattner 
TestBlocks(std::vector<const BasicBlock * > & BBs)4518bda4c49SChris Lattner bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
4528b2bd4edSMisha Brukman   // Clone the program to try hacking it apart...
453229e38f0SRafael Espindola   ValueToValueMapTy VMap;
454f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
455f32939bbSChris Lattner 
456f32939bbSChris Lattner   // Convert list to set for fast lookup...
457b294e31eSNick Lewycky   SmallPtrSet<BasicBlock *, 8> Blocks;
458b294e31eSNick Lewycky   for (unsigned i = 0, e = BBs.size(); i != e; ++i)
4590dc3c2d3SDevang Patel     Blocks.insert(cast<BasicBlock>(VMap[BBs[i]]));
460f32939bbSChris Lattner 
461ee05152cSDan Gohman   outs() << "Checking for crash with only these blocks:";
4624f50ebdaSChris Lattner   unsigned NumPrint = Blocks.size();
4638d0a0811SJustin Bogner   if (NumPrint > 10)
4648d0a0811SJustin Bogner     NumPrint = 10;
4654f50ebdaSChris Lattner   for (unsigned i = 0, e = NumPrint; i != e; ++i)
466ee05152cSDan Gohman     outs() << " " << BBs[i]->getName();
4674f50ebdaSChris Lattner   if (NumPrint < Blocks.size())
468ee05152cSDan Gohman     outs() << "... <" << Blocks.size() << " total>";
469ee05152cSDan Gohman   outs() << ": ";
470f32939bbSChris Lattner 
471f32939bbSChris Lattner   // Loop over and delete any hack up any blocks that are not listed...
472e84e7675SVedant Kumar   for (Function &F : M->functions()) {
473e84e7675SVedant Kumar     for (BasicBlock &BB : F) {
474e84e7675SVedant Kumar       if (!Blocks.count(&BB) && BB.getTerminator()->getNumSuccessors()) {
475f32939bbSChris Lattner         // Loop over all of the successors of this block, deleting any PHI nodes
476f32939bbSChris Lattner         // that might include it.
477e84e7675SVedant Kumar         for (BasicBlock *Succ : successors(&BB))
478e84e7675SVedant Kumar           Succ->removePredecessor(&BB);
479f32939bbSChris Lattner 
480e303c87eSChandler Carruth         Instruction *BBTerm = BB.getTerminator();
48129e641cdSPhilip Reames         if (BBTerm->isEHPad() || BBTerm->getType()->isTokenTy())
482189d7da1SDavid Majnemer           continue;
48329e641cdSPhilip Reames         if (!BBTerm->getType()->isVoidTy())
4845a1acd99SOwen Anderson           BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
4857855a5cbSChris Lattner 
4867855a5cbSChris Lattner         // Replace the old terminator instruction.
487e84e7675SVedant Kumar         BB.getInstList().pop_back();
488e84e7675SVedant Kumar         new UnreachableInst(BB.getContext(), &BB);
489e84e7675SVedant Kumar       }
490e84e7675SVedant Kumar     }
491f32939bbSChris Lattner   }
492f32939bbSChris Lattner 
493f32939bbSChris Lattner   // The CFG Simplifier pass may delete one of the basic blocks we are
494f32939bbSChris Lattner   // interested in.  If it does we need to take the block out of the list.  Make
495f32939bbSChris Lattner   // a "persistent mapping" by turning basic blocks into <function, name> pairs.
496f32939bbSChris Lattner   // This won't work well if blocks are unnamed, but that is just the risk we
497e84e7675SVedant Kumar   // have to take. FIXME: Can we just name the blocks?
498d1e241a4SRafael Espindola   std::vector<std::pair<std::string, std::string>> BlockInfo;
499f32939bbSChris Lattner 
5004627679cSCraig Topper   for (BasicBlock *BB : Blocks)
501cd87e207SBenjamin Kramer     BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
50249ad3f61SBenjamin Kramer                            std::string(BB->getName()));
503f32939bbSChris Lattner 
50460606266SDaniel Berlin   SmallVector<BasicBlock *, 16> ToProcess;
50560606266SDaniel Berlin   for (auto &F : *M) {
50660606266SDaniel Berlin     for (auto &BB : F)
50760606266SDaniel Berlin       if (!Blocks.count(&BB))
50860606266SDaniel Berlin         ToProcess.push_back(&BB);
50960606266SDaniel Berlin     simpleSimplifyCfg(F, ToProcess);
51060606266SDaniel Berlin     ToProcess.clear();
51160606266SDaniel Berlin   }
51260606266SDaniel Berlin   // Verify we didn't break anything
513d1e241a4SRafael Espindola   std::vector<std::string> Passes;
514d1e241a4SRafael Espindola   Passes.push_back("verify");
515e84e7675SVedant Kumar   std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
516d1e241a4SRafael Espindola   if (!New) {
51760606266SDaniel Berlin     errs() << "verify failed!\n";
518d1e241a4SRafael Espindola     exit(1);
519d1e241a4SRafael Espindola   }
520e84e7675SVedant Kumar   M = std::move(New);
521f32939bbSChris Lattner 
522f32939bbSChris Lattner   // Try running on the hacked up program...
523e84e7675SVedant Kumar   if (TestFn(BD, M.get())) {
524f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
525f32939bbSChris Lattner 
526f32939bbSChris Lattner     // Make sure to use basic block pointers that point into the now-current
527f32939bbSChris Lattner     // module, and that they don't include any deleted blocks.
528f32939bbSChris Lattner     BBs.clear();
529f6074ed9SRafael Espindola     const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
530e84e7675SVedant Kumar     for (const auto &BI : BlockInfo) {
531e84e7675SVedant Kumar       Function *F = cast<Function>(GST.lookup(BI.first));
532e84e7675SVedant Kumar       Value *V = F->getValueSymbolTable()->lookup(BI.second);
53355f1c09eSOwen Anderson       if (V && V->getType() == Type::getLabelTy(V->getContext()))
5343aaaa0b2SReid Spencer         BBs.push_back(cast<BasicBlock>(V));
535f32939bbSChris Lattner     }
536f32939bbSChris Lattner     return true;
537f32939bbSChris Lattner   }
538e84e7675SVedant Kumar   // It didn't crash, try something else.
539f32939bbSChris Lattner   return false;
540f32939bbSChris Lattner }
541f32939bbSChris Lattner 
5426e090c91SNick Lewycky namespace {
543271ca401SDaniel Berlin /// ReduceCrashingConditionals reducer - This works by changing
544271ca401SDaniel Berlin /// conditional branches to unconditional ones, then simplifying the CFG
545271ca401SDaniel Berlin /// This has the effect of chopping up the CFG really fast which can reduce
546271ca401SDaniel Berlin /// large functions quickly.
547271ca401SDaniel Berlin ///
548271ca401SDaniel Berlin class ReduceCrashingConditionals : public ListReducer<const BasicBlock *> {
549271ca401SDaniel Berlin   BugDriver &BD;
55008d829daSVedant Kumar   BugTester TestFn;
551271ca401SDaniel Berlin   bool Direction;
552271ca401SDaniel Berlin 
553271ca401SDaniel Berlin public:
ReduceCrashingConditionals(BugDriver & bd,BugTester testFn,bool Direction)55408d829daSVedant Kumar   ReduceCrashingConditionals(BugDriver &bd, BugTester testFn, bool Direction)
555271ca401SDaniel Berlin       : BD(bd), TestFn(testFn), Direction(Direction) {}
556271ca401SDaniel Berlin 
doTest(std::vector<const BasicBlock * > & Prefix,std::vector<const BasicBlock * > & Kept)5571c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
5581c039155SJustin Bogner                               std::vector<const BasicBlock *> &Kept) override {
559271ca401SDaniel Berlin     if (!Kept.empty() && TestBlocks(Kept))
560271ca401SDaniel Berlin       return KeepSuffix;
561271ca401SDaniel Berlin     if (!Prefix.empty() && TestBlocks(Prefix))
562271ca401SDaniel Berlin       return KeepPrefix;
563271ca401SDaniel Berlin     return NoFailure;
564271ca401SDaniel Berlin   }
565271ca401SDaniel Berlin 
566271ca401SDaniel Berlin   bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
567271ca401SDaniel Berlin };
568271ca401SDaniel Berlin }
569271ca401SDaniel Berlin 
TestBlocks(std::vector<const BasicBlock * > & BBs)570271ca401SDaniel Berlin bool ReduceCrashingConditionals::TestBlocks(
571271ca401SDaniel Berlin     std::vector<const BasicBlock *> &BBs) {
572271ca401SDaniel Berlin   // Clone the program to try hacking it apart...
573271ca401SDaniel Berlin   ValueToValueMapTy VMap;
574f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
575271ca401SDaniel Berlin 
576271ca401SDaniel Berlin   // Convert list to set for fast lookup...
577271ca401SDaniel Berlin   SmallPtrSet<const BasicBlock *, 8> Blocks;
578271ca401SDaniel Berlin   for (const auto *BB : BBs)
579271ca401SDaniel Berlin     Blocks.insert(cast<BasicBlock>(VMap[BB]));
580271ca401SDaniel Berlin 
581271ca401SDaniel Berlin   outs() << "Checking for crash with changing conditionals to always jump to "
582271ca401SDaniel Berlin          << (Direction ? "true" : "false") << ":";
583271ca401SDaniel Berlin   unsigned NumPrint = Blocks.size();
584271ca401SDaniel Berlin   if (NumPrint > 10)
585271ca401SDaniel Berlin     NumPrint = 10;
586271ca401SDaniel Berlin   for (unsigned i = 0, e = NumPrint; i != e; ++i)
587271ca401SDaniel Berlin     outs() << " " << BBs[i]->getName();
588271ca401SDaniel Berlin   if (NumPrint < Blocks.size())
589271ca401SDaniel Berlin     outs() << "... <" << Blocks.size() << " total>";
590271ca401SDaniel Berlin   outs() << ": ";
591271ca401SDaniel Berlin 
592271ca401SDaniel Berlin   // Loop over and delete any hack up any blocks that are not listed...
593271ca401SDaniel Berlin   for (auto &F : *M)
594271ca401SDaniel Berlin     for (auto &BB : F)
595271ca401SDaniel Berlin       if (!Blocks.count(&BB)) {
596271ca401SDaniel Berlin         auto *BR = dyn_cast<BranchInst>(BB.getTerminator());
597271ca401SDaniel Berlin         if (!BR || !BR->isConditional())
598271ca401SDaniel Berlin           continue;
599271ca401SDaniel Berlin         if (Direction)
600271ca401SDaniel Berlin           BR->setCondition(ConstantInt::getTrue(BR->getContext()));
601271ca401SDaniel Berlin         else
602271ca401SDaniel Berlin           BR->setCondition(ConstantInt::getFalse(BR->getContext()));
603271ca401SDaniel Berlin       }
604271ca401SDaniel Berlin 
605271ca401SDaniel Berlin   // The following may destroy some blocks, so we save them first
606271ca401SDaniel Berlin   std::vector<std::pair<std::string, std::string>> BlockInfo;
607271ca401SDaniel Berlin 
608271ca401SDaniel Berlin   for (const BasicBlock *BB : Blocks)
60942a25e7fSBenjamin Kramer     BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
61049ad3f61SBenjamin Kramer                            std::string(BB->getName()));
611271ca401SDaniel Berlin 
612271ca401SDaniel Berlin   SmallVector<BasicBlock *, 16> ToProcess;
613271ca401SDaniel Berlin   for (auto &F : *M) {
614271ca401SDaniel Berlin     for (auto &BB : F)
615271ca401SDaniel Berlin       if (!Blocks.count(&BB))
616271ca401SDaniel Berlin         ToProcess.push_back(&BB);
617271ca401SDaniel Berlin     simpleSimplifyCfg(F, ToProcess);
618271ca401SDaniel Berlin     ToProcess.clear();
619271ca401SDaniel Berlin   }
620271ca401SDaniel Berlin   // Verify we didn't break anything
621271ca401SDaniel Berlin   std::vector<std::string> Passes;
622271ca401SDaniel Berlin   Passes.push_back("verify");
623e84e7675SVedant Kumar   std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
624271ca401SDaniel Berlin   if (!New) {
625271ca401SDaniel Berlin     errs() << "verify failed!\n";
626271ca401SDaniel Berlin     exit(1);
627271ca401SDaniel Berlin   }
628e84e7675SVedant Kumar   M = std::move(New);
629271ca401SDaniel Berlin 
630271ca401SDaniel Berlin   // Try running on the hacked up program...
631e84e7675SVedant Kumar   if (TestFn(BD, M.get())) {
632f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
633271ca401SDaniel Berlin 
634271ca401SDaniel Berlin     // Make sure to use basic block pointers that point into the now-current
635271ca401SDaniel Berlin     // module, and that they don't include any deleted blocks.
636271ca401SDaniel Berlin     BBs.clear();
637f6074ed9SRafael Espindola     const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
638271ca401SDaniel Berlin     for (auto &BI : BlockInfo) {
639271ca401SDaniel Berlin       auto *F = cast<Function>(GST.lookup(BI.first));
640a53d49e1SMehdi Amini       Value *V = F->getValueSymbolTable()->lookup(BI.second);
641271ca401SDaniel Berlin       if (V && V->getType() == Type::getLabelTy(V->getContext()))
642271ca401SDaniel Berlin         BBs.push_back(cast<BasicBlock>(V));
643271ca401SDaniel Berlin     }
644271ca401SDaniel Berlin     return true;
645271ca401SDaniel Berlin   }
646e84e7675SVedant Kumar   // It didn't crash, try something else.
647271ca401SDaniel Berlin   return false;
648271ca401SDaniel Berlin }
649271ca401SDaniel Berlin 
650271ca401SDaniel Berlin namespace {
65160606266SDaniel Berlin /// SimplifyCFG reducer - This works by calling SimplifyCFG on each basic block
65260606266SDaniel Berlin /// in the program.
65360606266SDaniel Berlin 
65460606266SDaniel Berlin class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {
65560606266SDaniel Berlin   BugDriver &BD;
65608d829daSVedant Kumar   BugTester TestFn;
65760606266SDaniel Berlin   TargetTransformInfo TTI;
65860606266SDaniel Berlin 
65960606266SDaniel Berlin public:
ReduceSimplifyCFG(BugDriver & bd,BugTester testFn)66008d829daSVedant Kumar   ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)
661f6074ed9SRafael Espindola       : BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}
66260606266SDaniel Berlin 
doTest(std::vector<const BasicBlock * > & Prefix,std::vector<const BasicBlock * > & Kept)6631c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
6641c039155SJustin Bogner                               std::vector<const BasicBlock *> &Kept) override {
66560606266SDaniel Berlin     if (!Kept.empty() && TestBlocks(Kept))
66660606266SDaniel Berlin       return KeepSuffix;
66760606266SDaniel Berlin     if (!Prefix.empty() && TestBlocks(Prefix))
66860606266SDaniel Berlin       return KeepPrefix;
66960606266SDaniel Berlin     return NoFailure;
67060606266SDaniel Berlin   }
67160606266SDaniel Berlin 
67260606266SDaniel Berlin   bool TestBlocks(std::vector<const BasicBlock *> &Prefix);
67360606266SDaniel Berlin };
67460606266SDaniel Berlin }
67560606266SDaniel Berlin 
TestBlocks(std::vector<const BasicBlock * > & BBs)6768d0a0811SJustin Bogner bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
67760606266SDaniel Berlin   // Clone the program to try hacking it apart...
67860606266SDaniel Berlin   ValueToValueMapTy VMap;
679f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
68060606266SDaniel Berlin 
68160606266SDaniel Berlin   // Convert list to set for fast lookup...
68260606266SDaniel Berlin   SmallPtrSet<const BasicBlock *, 8> Blocks;
68360606266SDaniel Berlin   for (const auto *BB : BBs)
68460606266SDaniel Berlin     Blocks.insert(cast<BasicBlock>(VMap[BB]));
68560606266SDaniel Berlin 
68660606266SDaniel Berlin   outs() << "Checking for crash with CFG simplifying:";
68760606266SDaniel Berlin   unsigned NumPrint = Blocks.size();
68860606266SDaniel Berlin   if (NumPrint > 10)
68960606266SDaniel Berlin     NumPrint = 10;
69060606266SDaniel Berlin   for (unsigned i = 0, e = NumPrint; i != e; ++i)
69160606266SDaniel Berlin     outs() << " " << BBs[i]->getName();
69260606266SDaniel Berlin   if (NumPrint < Blocks.size())
69360606266SDaniel Berlin     outs() << "... <" << Blocks.size() << " total>";
69460606266SDaniel Berlin   outs() << ": ";
69560606266SDaniel Berlin 
69660606266SDaniel Berlin   // The following may destroy some blocks, so we save them first
69760606266SDaniel Berlin   std::vector<std::pair<std::string, std::string>> BlockInfo;
69860606266SDaniel Berlin 
69960606266SDaniel Berlin   for (const BasicBlock *BB : Blocks)
70042a25e7fSBenjamin Kramer     BlockInfo.emplace_back(std::string(BB->getParent()->getName()),
70149ad3f61SBenjamin Kramer                            std::string(BB->getName()));
70260606266SDaniel Berlin 
70360606266SDaniel Berlin   // Loop over and delete any hack up any blocks that are not listed...
70460606266SDaniel Berlin   for (auto &F : *M)
70560606266SDaniel Berlin     // Loop over all of the basic blocks and remove them if they are unneeded.
70660606266SDaniel Berlin     for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {
70760606266SDaniel Berlin       if (!Blocks.count(&*BBIt)) {
70860606266SDaniel Berlin         ++BBIt;
70960606266SDaniel Berlin         continue;
71060606266SDaniel Berlin       }
7114c33d521SSanjay Patel       simplifyCFG(&*BBIt++, TTI);
71260606266SDaniel Berlin     }
71360606266SDaniel Berlin   // Verify we didn't break anything
71460606266SDaniel Berlin   std::vector<std::string> Passes;
71560606266SDaniel Berlin   Passes.push_back("verify");
716e84e7675SVedant Kumar   std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
71760606266SDaniel Berlin   if (!New) {
71860606266SDaniel Berlin     errs() << "verify failed!\n";
71960606266SDaniel Berlin     exit(1);
72060606266SDaniel Berlin   }
721e84e7675SVedant Kumar   M = std::move(New);
72260606266SDaniel Berlin 
72360606266SDaniel Berlin   // Try running on the hacked up program...
724e84e7675SVedant Kumar   if (TestFn(BD, M.get())) {
725f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
72660606266SDaniel Berlin 
72760606266SDaniel Berlin     // Make sure to use basic block pointers that point into the now-current
72860606266SDaniel Berlin     // module, and that they don't include any deleted blocks.
72960606266SDaniel Berlin     BBs.clear();
730f6074ed9SRafael Espindola     const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
73160606266SDaniel Berlin     for (auto &BI : BlockInfo) {
73260606266SDaniel Berlin       auto *F = cast<Function>(GST.lookup(BI.first));
733a53d49e1SMehdi Amini       Value *V = F->getValueSymbolTable()->lookup(BI.second);
73460606266SDaniel Berlin       if (V && V->getType() == Type::getLabelTy(V->getContext()))
73560606266SDaniel Berlin         BBs.push_back(cast<BasicBlock>(V));
73660606266SDaniel Berlin     }
73760606266SDaniel Berlin     return true;
73860606266SDaniel Berlin   }
739e84e7675SVedant Kumar   // It didn't crash, try something else.
74060606266SDaniel Berlin   return false;
74160606266SDaniel Berlin }
74260606266SDaniel Berlin 
74360606266SDaniel Berlin namespace {
7446e090c91SNick Lewycky /// ReduceCrashingInstructions reducer - This works by removing the specified
7456e090c91SNick Lewycky /// non-terminator instructions and replacing them with undef.
7466e090c91SNick Lewycky ///
7476e090c91SNick Lewycky class ReduceCrashingInstructions : public ListReducer<const Instruction *> {
7486e090c91SNick Lewycky   BugDriver &BD;
74908d829daSVedant Kumar   BugTester TestFn;
7508d0a0811SJustin Bogner 
7516e090c91SNick Lewycky public:
ReduceCrashingInstructions(BugDriver & bd,BugTester testFn)75208d829daSVedant Kumar   ReduceCrashingInstructions(BugDriver &bd, BugTester testFn)
7536e090c91SNick Lewycky       : BD(bd), TestFn(testFn) {}
7546e090c91SNick Lewycky 
doTest(std::vector<const Instruction * > & Prefix,std::vector<const Instruction * > & Kept)7551c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<const Instruction *> &Prefix,
7561c039155SJustin Bogner                               std::vector<const Instruction *> &Kept) override {
7576e090c91SNick Lewycky     if (!Kept.empty() && TestInsts(Kept))
7586e090c91SNick Lewycky       return KeepSuffix;
7596e090c91SNick Lewycky     if (!Prefix.empty() && TestInsts(Prefix))
7606e090c91SNick Lewycky       return KeepPrefix;
7616e090c91SNick Lewycky     return NoFailure;
7626e090c91SNick Lewycky   }
7636e090c91SNick Lewycky 
7646e090c91SNick Lewycky   bool TestInsts(std::vector<const Instruction *> &Prefix);
7656e090c91SNick Lewycky };
7666e090c91SNick Lewycky }
7676e090c91SNick Lewycky 
TestInsts(std::vector<const Instruction * > & Insts)7688d0a0811SJustin Bogner bool ReduceCrashingInstructions::TestInsts(
7698d0a0811SJustin Bogner     std::vector<const Instruction *> &Insts) {
7706e090c91SNick Lewycky   // Clone the program to try hacking it apart...
771229e38f0SRafael Espindola   ValueToValueMapTy VMap;
772f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
7736e090c91SNick Lewycky 
7746e090c91SNick Lewycky   // Convert list to set for fast lookup...
775b30f2f51SMatthias Braun   SmallPtrSet<Instruction *, 32> Instructions;
7766e090c91SNick Lewycky   for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
7779ae926b9SChandler Carruth     assert(!Insts[i]->isTerminator());
7780dc3c2d3SDevang Patel     Instructions.insert(cast<Instruction>(VMap[Insts[i]]));
7796e090c91SNick Lewycky   }
7806e090c91SNick Lewycky 
781ee05152cSDan Gohman   outs() << "Checking for crash with only " << Instructions.size();
7826e090c91SNick Lewycky   if (Instructions.size() == 1)
783ee05152cSDan Gohman     outs() << " instruction: ";
7846e090c91SNick Lewycky   else
785ee05152cSDan Gohman     outs() << " instructions: ";
7866e090c91SNick Lewycky 
7876e090c91SNick Lewycky   for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI)
7886e090c91SNick Lewycky     for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI)
78987e53a0aSKazu Hirata       for (Instruction &Inst : llvm::make_early_inc_range(*FI)) {
79087e53a0aSKazu Hirata         if (!Instructions.count(&Inst) && !Inst.isTerminator() &&
79187e53a0aSKazu Hirata             !Inst.isEHPad() && !Inst.getType()->isTokenTy() &&
79287e53a0aSKazu Hirata             !Inst.isSwiftError()) {
79387e53a0aSKazu Hirata           if (!Inst.getType()->isVoidTy())
79487e53a0aSKazu Hirata             Inst.replaceAllUsesWith(UndefValue::get(Inst.getType()));
79587e53a0aSKazu Hirata           Inst.eraseFromParent();
7966e090c91SNick Lewycky         }
7976e090c91SNick Lewycky       }
7986e090c91SNick Lewycky 
7996e090c91SNick Lewycky   // Verify that this is still valid.
80030d69c2eSChandler Carruth   legacy::PassManager Passes;
801919bdf1dSAdrian Prantl   Passes.add(createVerifierPass(/*FatalErrors=*/false));
8026e090c91SNick Lewycky   Passes.run(*M);
8036e090c91SNick Lewycky 
8046e090c91SNick Lewycky   // Try running on the hacked up program...
80519d8655cSRafael Espindola   if (TestFn(BD, M.get())) {
806f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
8076e090c91SNick Lewycky 
8086e090c91SNick Lewycky     // Make sure to use instruction pointers that point into the now-current
8096e090c91SNick Lewycky     // module, and that they don't include any deleted blocks.
8106e090c91SNick Lewycky     Insts.clear();
8114627679cSCraig Topper     for (Instruction *Inst : Instructions)
8124627679cSCraig Topper       Insts.push_back(Inst);
8136e090c91SNick Lewycky     return true;
8146e090c91SNick Lewycky   }
81519d8655cSRafael Espindola   // It didn't crash, try something else.
8166e090c91SNick Lewycky   return false;
8176e090c91SNick Lewycky }
8186e090c91SNick Lewycky 
81934ca831dSKeno Fischer namespace {
82029e8b8ceSFlorian Hahn /// ReduceCrashingMetadata reducer - This works by removing all metadata from
82129e8b8ceSFlorian Hahn /// the specified instructions.
82229e8b8ceSFlorian Hahn ///
82329e8b8ceSFlorian Hahn class ReduceCrashingMetadata : public ListReducer<Instruction *> {
82429e8b8ceSFlorian Hahn   BugDriver &BD;
82529e8b8ceSFlorian Hahn   BugTester TestFn;
82629e8b8ceSFlorian Hahn 
82729e8b8ceSFlorian Hahn public:
ReduceCrashingMetadata(BugDriver & bd,BugTester testFn)82829e8b8ceSFlorian Hahn   ReduceCrashingMetadata(BugDriver &bd, BugTester testFn)
82929e8b8ceSFlorian Hahn       : BD(bd), TestFn(testFn) {}
83029e8b8ceSFlorian Hahn 
doTest(std::vector<Instruction * > & Prefix,std::vector<Instruction * > & Kept)83129e8b8ceSFlorian Hahn   Expected<TestResult> doTest(std::vector<Instruction *> &Prefix,
83229e8b8ceSFlorian Hahn                               std::vector<Instruction *> &Kept) override {
83329e8b8ceSFlorian Hahn     if (!Kept.empty() && TestInsts(Kept))
83429e8b8ceSFlorian Hahn       return KeepSuffix;
83529e8b8ceSFlorian Hahn     if (!Prefix.empty() && TestInsts(Prefix))
83629e8b8ceSFlorian Hahn       return KeepPrefix;
83729e8b8ceSFlorian Hahn     return NoFailure;
83829e8b8ceSFlorian Hahn   }
83929e8b8ceSFlorian Hahn 
84029e8b8ceSFlorian Hahn   bool TestInsts(std::vector<Instruction *> &Prefix);
84129e8b8ceSFlorian Hahn };
84229e8b8ceSFlorian Hahn } // namespace
84329e8b8ceSFlorian Hahn 
TestInsts(std::vector<Instruction * > & Insts)84429e8b8ceSFlorian Hahn bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {
84529e8b8ceSFlorian Hahn   // Clone the program to try hacking it apart...
84629e8b8ceSFlorian Hahn   ValueToValueMapTy VMap;
84729e8b8ceSFlorian Hahn   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
84829e8b8ceSFlorian Hahn 
84929e8b8ceSFlorian Hahn   // Convert list to set for fast lookup...
85029e8b8ceSFlorian Hahn   SmallPtrSet<Instruction *, 32> Instructions;
85129e8b8ceSFlorian Hahn   for (Instruction *I : Insts)
85229e8b8ceSFlorian Hahn     Instructions.insert(cast<Instruction>(VMap[I]));
85329e8b8ceSFlorian Hahn 
85429e8b8ceSFlorian Hahn   outs() << "Checking for crash with metadata retained from "
85529e8b8ceSFlorian Hahn          << Instructions.size();
85629e8b8ceSFlorian Hahn   if (Instructions.size() == 1)
85729e8b8ceSFlorian Hahn     outs() << " instruction: ";
85829e8b8ceSFlorian Hahn   else
85929e8b8ceSFlorian Hahn     outs() << " instructions: ";
86029e8b8ceSFlorian Hahn 
86129e8b8ceSFlorian Hahn   // Try to drop instruction metadata from all instructions, except the ones
86229e8b8ceSFlorian Hahn   // selected in Instructions.
86329e8b8ceSFlorian Hahn   for (Function &F : *M)
86429e8b8ceSFlorian Hahn     for (Instruction &Inst : instructions(F)) {
8653badd17bSBenjamin Kramer       if (!Instructions.count(&Inst)) {
86629e8b8ceSFlorian Hahn         Inst.dropUnknownNonDebugMetadata();
86729e8b8ceSFlorian Hahn         Inst.setDebugLoc({});
86829e8b8ceSFlorian Hahn       }
86929e8b8ceSFlorian Hahn     }
87029e8b8ceSFlorian Hahn 
87129e8b8ceSFlorian Hahn   // Verify that this is still valid.
87229e8b8ceSFlorian Hahn   legacy::PassManager Passes;
87329e8b8ceSFlorian Hahn   Passes.add(createVerifierPass(/*FatalErrors=*/false));
87429e8b8ceSFlorian Hahn   Passes.run(*M);
87529e8b8ceSFlorian Hahn 
87629e8b8ceSFlorian Hahn   // Try running on the hacked up program...
87729e8b8ceSFlorian Hahn   if (TestFn(BD, M.get())) {
87829e8b8ceSFlorian Hahn     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
87929e8b8ceSFlorian Hahn 
88029e8b8ceSFlorian Hahn     // Make sure to use instruction pointers that point into the now-current
88129e8b8ceSFlorian Hahn     // module, and that they don't include any deleted blocks.
88229e8b8ceSFlorian Hahn     Insts.clear();
88329e8b8ceSFlorian Hahn     for (Instruction *I : Instructions)
88429e8b8ceSFlorian Hahn       Insts.push_back(I);
88529e8b8ceSFlorian Hahn     return true;
88629e8b8ceSFlorian Hahn   }
88729e8b8ceSFlorian Hahn   // It didn't crash, try something else.
88829e8b8ceSFlorian Hahn   return false;
88929e8b8ceSFlorian Hahn }
89029e8b8ceSFlorian Hahn 
89129e8b8ceSFlorian Hahn namespace {
89234ca831dSKeno Fischer // Reduce the list of Named Metadata nodes. We keep this as a list of
89334ca831dSKeno Fischer // names to avoid having to convert back and forth every time.
89434ca831dSKeno Fischer class ReduceCrashingNamedMD : public ListReducer<std::string> {
89534ca831dSKeno Fischer   BugDriver &BD;
89608d829daSVedant Kumar   BugTester TestFn;
89734ca831dSKeno Fischer 
89834ca831dSKeno Fischer public:
ReduceCrashingNamedMD(BugDriver & bd,BugTester testFn)89908d829daSVedant Kumar   ReduceCrashingNamedMD(BugDriver &bd, BugTester testFn)
90034ca831dSKeno Fischer       : BD(bd), TestFn(testFn) {}
90134ca831dSKeno Fischer 
doTest(std::vector<std::string> & Prefix,std::vector<std::string> & Kept)9021c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<std::string> &Prefix,
9031c039155SJustin Bogner                               std::vector<std::string> &Kept) override {
90434ca831dSKeno Fischer     if (!Kept.empty() && TestNamedMDs(Kept))
90534ca831dSKeno Fischer       return KeepSuffix;
90634ca831dSKeno Fischer     if (!Prefix.empty() && TestNamedMDs(Prefix))
90734ca831dSKeno Fischer       return KeepPrefix;
90834ca831dSKeno Fischer     return NoFailure;
90934ca831dSKeno Fischer   }
91034ca831dSKeno Fischer 
91134ca831dSKeno Fischer   bool TestNamedMDs(std::vector<std::string> &NamedMDs);
91234ca831dSKeno Fischer };
91334ca831dSKeno Fischer }
91434ca831dSKeno Fischer 
TestNamedMDs(std::vector<std::string> & NamedMDs)91534ca831dSKeno Fischer bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
91634ca831dSKeno Fischer 
91734ca831dSKeno Fischer   ValueToValueMapTy VMap;
918f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
91934ca831dSKeno Fischer 
92034ca831dSKeno Fischer   outs() << "Checking for crash with only these named metadata nodes:";
92134ca831dSKeno Fischer   unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
92234ca831dSKeno Fischer   for (unsigned i = 0, e = NumPrint; i != e; ++i)
92334ca831dSKeno Fischer     outs() << " " << NamedMDs[i];
92434ca831dSKeno Fischer   if (NumPrint < NamedMDs.size())
92534ca831dSKeno Fischer     outs() << "... <" << NamedMDs.size() << " total>";
92634ca831dSKeno Fischer   outs() << ": ";
92734ca831dSKeno Fischer 
92834ca831dSKeno Fischer   // Make a StringMap for faster lookup
92934ca831dSKeno Fischer   StringSet<> Names;
93034ca831dSKeno Fischer   for (const std::string &Name : NamedMDs)
93134ca831dSKeno Fischer     Names.insert(Name);
93234ca831dSKeno Fischer 
93334ca831dSKeno Fischer   // First collect all the metadata to delete in a vector, then
93434ca831dSKeno Fischer   // delete them all at once to avoid invalidating the iterator
93534ca831dSKeno Fischer   std::vector<NamedMDNode *> ToDelete;
93634ca831dSKeno Fischer   ToDelete.reserve(M->named_metadata_size() - Names.size());
93734ca831dSKeno Fischer   for (auto &NamedMD : M->named_metadata())
938faebbb05SAdrian Prantl     // Always keep a nonempty llvm.dbg.cu because the Verifier would complain.
939faebbb05SAdrian Prantl     if (!Names.count(NamedMD.getName()) &&
940faebbb05SAdrian Prantl         (!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0)))
94134ca831dSKeno Fischer       ToDelete.push_back(&NamedMD);
94234ca831dSKeno Fischer 
94334ca831dSKeno Fischer   for (auto *NamedMD : ToDelete)
94434ca831dSKeno Fischer     NamedMD->eraseFromParent();
94534ca831dSKeno Fischer 
94634ca831dSKeno Fischer   // Verify that this is still valid.
94734ca831dSKeno Fischer   legacy::PassManager Passes;
948919bdf1dSAdrian Prantl   Passes.add(createVerifierPass(/*FatalErrors=*/false));
94934ca831dSKeno Fischer   Passes.run(*M);
95034ca831dSKeno Fischer 
95134ca831dSKeno Fischer   // Try running on the hacked up program...
9522911841fSRafael Espindola   if (TestFn(BD, M.get())) {
953f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
95434ca831dSKeno Fischer     return true;
95534ca831dSKeno Fischer   }
95634ca831dSKeno Fischer   return false;
95734ca831dSKeno Fischer }
95834ca831dSKeno Fischer 
95934ca831dSKeno Fischer namespace {
96034ca831dSKeno Fischer // Reduce the list of operands to named metadata nodes
96134ca831dSKeno Fischer class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {
96234ca831dSKeno Fischer   BugDriver &BD;
96308d829daSVedant Kumar   BugTester TestFn;
96434ca831dSKeno Fischer 
96534ca831dSKeno Fischer public:
ReduceCrashingNamedMDOps(BugDriver & bd,BugTester testFn)96608d829daSVedant Kumar   ReduceCrashingNamedMDOps(BugDriver &bd, BugTester testFn)
96734ca831dSKeno Fischer       : BD(bd), TestFn(testFn) {}
96834ca831dSKeno Fischer 
doTest(std::vector<const MDNode * > & Prefix,std::vector<const MDNode * > & Kept)9691c039155SJustin Bogner   Expected<TestResult> doTest(std::vector<const MDNode *> &Prefix,
9701c039155SJustin Bogner                               std::vector<const MDNode *> &Kept) override {
97134ca831dSKeno Fischer     if (!Kept.empty() && TestNamedMDOps(Kept))
97234ca831dSKeno Fischer       return KeepSuffix;
97334ca831dSKeno Fischer     if (!Prefix.empty() && TestNamedMDOps(Prefix))
97434ca831dSKeno Fischer       return KeepPrefix;
97534ca831dSKeno Fischer     return NoFailure;
97634ca831dSKeno Fischer   }
97734ca831dSKeno Fischer 
97834ca831dSKeno Fischer   bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps);
97934ca831dSKeno Fischer };
98034ca831dSKeno Fischer }
98134ca831dSKeno Fischer 
TestNamedMDOps(std::vector<const MDNode * > & NamedMDOps)98234ca831dSKeno Fischer bool ReduceCrashingNamedMDOps::TestNamedMDOps(
98334ca831dSKeno Fischer     std::vector<const MDNode *> &NamedMDOps) {
98434ca831dSKeno Fischer   // Convert list to set for fast lookup...
985b30f2f51SMatthias Braun   SmallPtrSet<const MDNode *, 32> OldMDNodeOps;
98634ca831dSKeno Fischer   for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) {
98734ca831dSKeno Fischer     OldMDNodeOps.insert(NamedMDOps[i]);
98834ca831dSKeno Fischer   }
98934ca831dSKeno Fischer 
99034ca831dSKeno Fischer   outs() << "Checking for crash with only " << OldMDNodeOps.size();
99134ca831dSKeno Fischer   if (OldMDNodeOps.size() == 1)
99234ca831dSKeno Fischer     outs() << " named metadata operand: ";
99334ca831dSKeno Fischer   else
99434ca831dSKeno Fischer     outs() << " named metadata operands: ";
99534ca831dSKeno Fischer 
99634ca831dSKeno Fischer   ValueToValueMapTy VMap;
997f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
99834ca831dSKeno Fischer 
99934ca831dSKeno Fischer   // This is a little wasteful. In the future it might be good if we could have
100034ca831dSKeno Fischer   // these dropped during cloning.
1001f6074ed9SRafael Espindola   for (auto &NamedMD : BD.getProgram().named_metadata()) {
100234ca831dSKeno Fischer     // Drop the old one and create a new one
100334ca831dSKeno Fischer     M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
100434ca831dSKeno Fischer     NamedMDNode *NewNamedMDNode =
100534ca831dSKeno Fischer         M->getOrInsertNamedMetadata(NamedMD.getName());
100634ca831dSKeno Fischer     for (MDNode *op : NamedMD.operands())
100734ca831dSKeno Fischer       if (OldMDNodeOps.count(op))
100834ca831dSKeno Fischer         NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap)));
100934ca831dSKeno Fischer   }
101034ca831dSKeno Fischer 
101134ca831dSKeno Fischer   // Verify that this is still valid.
101234ca831dSKeno Fischer   legacy::PassManager Passes;
1013919bdf1dSAdrian Prantl   Passes.add(createVerifierPass(/*FatalErrors=*/false));
101434ca831dSKeno Fischer   Passes.run(*M);
101534ca831dSKeno Fischer 
101634ca831dSKeno Fischer   // Try running on the hacked up program...
101702a3fb15SRafael Espindola   if (TestFn(BD, M.get())) {
101834ca831dSKeno Fischer     // Make sure to use instruction pointers that point into the now-current
101934ca831dSKeno Fischer     // module, and that they don't include any deleted blocks.
102034ca831dSKeno Fischer     NamedMDOps.clear();
102134ca831dSKeno Fischer     for (const MDNode *Node : OldMDNodeOps)
1022da4a56d1SDuncan P. N. Exon Smith       NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));
102334ca831dSKeno Fischer 
1024f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
102534ca831dSKeno Fischer     return true;
102634ca831dSKeno Fischer   }
102702a3fb15SRafael Espindola   // It didn't crash, try something else.
102834ca831dSKeno Fischer   return false;
102934ca831dSKeno Fischer }
103034ca831dSKeno Fischer 
103166e85e6cSVedant Kumar /// Attempt to eliminate as many global initializers as possible.
ReduceGlobalInitializers(BugDriver & BD,BugTester TestFn)103208d829daSVedant Kumar static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
1033f6074ed9SRafael Espindola   Module &OrigM = BD.getProgram();
1034f6074ed9SRafael Espindola   if (OrigM.global_empty())
103566e85e6cSVedant Kumar     return Error::success();
103666e85e6cSVedant Kumar 
10373f83343cSBill Wendling   // Now try to reduce the number of global variable initializers in the
10383f83343cSBill Wendling   // module to something small.
1039f6074ed9SRafael Espindola   std::unique_ptr<Module> M = CloneModule(OrigM);
104074a4a2a8SBill Wendling   bool DeletedInit = false;
104174a4a2a8SBill Wendling 
104266e85e6cSVedant Kumar   for (GlobalVariable &GV : M->globals()) {
104366e85e6cSVedant Kumar     if (GV.hasInitializer()) {
104466e85e6cSVedant Kumar       DeleteGlobalInitializer(&GV);
104566e85e6cSVedant Kumar       GV.setLinkage(GlobalValue::ExternalLinkage);
104666e85e6cSVedant Kumar       GV.setComdat(nullptr);
104774a4a2a8SBill Wendling       DeletedInit = true;
104874a4a2a8SBill Wendling     }
104966e85e6cSVedant Kumar   }
105074a4a2a8SBill Wendling 
105166e85e6cSVedant Kumar   if (!DeletedInit)
105266e85e6cSVedant Kumar     return Error::success();
105366e85e6cSVedant Kumar 
105474a4a2a8SBill Wendling   // See if the program still causes a crash...
1055ee05152cSDan Gohman   outs() << "\nChecking to see if we can delete global inits: ";
105674a4a2a8SBill Wendling 
105766e85e6cSVedant Kumar   if (TestFn(BD, M.get())) { // Still crashes?
1058f6074ed9SRafael Espindola     BD.setNewProgram(std::move(M));
1059ee05152cSDan Gohman     outs() << "\n*** Able to remove all global initializers!\n";
106066e85e6cSVedant Kumar     return Error::success();
106166e85e6cSVedant Kumar   }
106266e85e6cSVedant Kumar 
106366e85e6cSVedant Kumar   // No longer crashes.
1064ee05152cSDan Gohman   outs() << "  - Removing all global inits hides problem!\n";
106574a4a2a8SBill Wendling 
10663f83343cSBill Wendling   std::vector<GlobalVariable *> GVs;
1067f6074ed9SRafael Espindola   for (GlobalVariable &GV : OrigM.globals())
106866e85e6cSVedant Kumar     if (GV.hasInitializer())
106966e85e6cSVedant Kumar       GVs.push_back(&GV);
10703f83343cSBill Wendling 
10713f83343cSBill Wendling   if (GVs.size() > 1 && !BugpointIsInterrupted) {
107266e85e6cSVedant Kumar     outs() << "\n*** Attempting to reduce the number of global initializers "
107366e85e6cSVedant Kumar            << "in the testcase\n";
10743f83343cSBill Wendling 
10753f83343cSBill Wendling     unsigned OldSize = GVs.size();
10761c039155SJustin Bogner     Expected<bool> Result =
107766e85e6cSVedant Kumar         ReduceCrashingGlobalInitializers(BD, TestFn).reduceList(GVs);
10781c039155SJustin Bogner     if (Error E = Result.takeError())
10791c039155SJustin Bogner       return E;
10803f83343cSBill Wendling 
10813f83343cSBill Wendling     if (GVs.size() < OldSize)
1082594994a3SRafael Espindola       BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");
108365e5f653SChris Lattner   }
10841c039155SJustin Bogner   return Error::success();
10851c232f9bSPhilip Reames }
10861c232f9bSPhilip Reames 
ReduceInsts(BugDriver & BD,BugTester TestFn)108708d829daSVedant Kumar static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
10881c232f9bSPhilip Reames   // Attempt to delete instructions using bisection. This should help out nasty
10891c232f9bSPhilip Reames   // cases with large basic blocks where the problem is at one end.
10901c232f9bSPhilip Reames   if (!BugpointIsInterrupted) {
10911c232f9bSPhilip Reames     std::vector<const Instruction *> Insts;
1092f6074ed9SRafael Espindola     for (const Function &F : BD.getProgram())
10931c232f9bSPhilip Reames       for (const BasicBlock &BB : F)
10941c232f9bSPhilip Reames         for (const Instruction &I : BB)
10959ae926b9SChandler Carruth           if (!I.isTerminator())
10961c232f9bSPhilip Reames             Insts.push_back(&I);
10971c232f9bSPhilip Reames 
10981c039155SJustin Bogner     Expected<bool> Result =
10991c039155SJustin Bogner         ReduceCrashingInstructions(BD, TestFn).reduceList(Insts);
11001c039155SJustin Bogner     if (Error E = Result.takeError())
11011c039155SJustin Bogner       return E;
11021c232f9bSPhilip Reames   }
11031c232f9bSPhilip Reames 
11041c232f9bSPhilip Reames   unsigned Simplification = 2;
11051c232f9bSPhilip Reames   do {
11061c232f9bSPhilip Reames     if (BugpointIsInterrupted)
11071c039155SJustin Bogner       // TODO: Should we distinguish this with an "interrupted error"?
11081c039155SJustin Bogner       return Error::success();
11091c232f9bSPhilip Reames     --Simplification;
11101c232f9bSPhilip Reames     outs() << "\n*** Attempting to reduce testcase by deleting instruc"
11111c232f9bSPhilip Reames            << "tions: Simplification Level #" << Simplification << '\n';
11121c232f9bSPhilip Reames 
11131c232f9bSPhilip Reames     // Now that we have deleted the functions that are unnecessary for the
11141c232f9bSPhilip Reames     // program, try to remove instructions that are not necessary to cause the
11151c232f9bSPhilip Reames     // crash.  To do this, we loop through all of the instructions in the
11161c232f9bSPhilip Reames     // remaining functions, deleting them (replacing any values produced with
11171c232f9bSPhilip Reames     // nulls), and then running ADCE and SimplifyCFG.  If the transformed input
11181c232f9bSPhilip Reames     // still triggers failure, keep deleting until we cannot trigger failure
11191c232f9bSPhilip Reames     // anymore.
11201c232f9bSPhilip Reames     //
11211c232f9bSPhilip Reames     unsigned InstructionsToSkipBeforeDeleting = 0;
11221c232f9bSPhilip Reames   TryAgain:
11231c232f9bSPhilip Reames 
11241c232f9bSPhilip Reames     // Loop over all of the (non-terminator) instructions remaining in the
11251c232f9bSPhilip Reames     // function, attempting to delete them.
11261c232f9bSPhilip Reames     unsigned CurInstructionNum = 0;
1127f6074ed9SRafael Espindola     for (Module::const_iterator FI = BD.getProgram().begin(),
1128f6074ed9SRafael Espindola                                 E = BD.getProgram().end();
11298d0a0811SJustin Bogner          FI != E; ++FI)
11301c232f9bSPhilip Reames       if (!FI->isDeclaration())
11311c232f9bSPhilip Reames         for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;
11321c232f9bSPhilip Reames              ++BI)
11331c232f9bSPhilip Reames           for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end();
11341c232f9bSPhilip Reames                I != E; ++I, ++CurInstructionNum) {
11351c232f9bSPhilip Reames             if (InstructionsToSkipBeforeDeleting) {
11361c232f9bSPhilip Reames               --InstructionsToSkipBeforeDeleting;
11371c232f9bSPhilip Reames             } else {
11381c232f9bSPhilip Reames               if (BugpointIsInterrupted)
11391c039155SJustin Bogner                 // TODO: Should this be some kind of interrupted error?
11401c039155SJustin Bogner                 return Error::success();
11411c232f9bSPhilip Reames 
1142a8f5a829SArnold Schwaighofer               if (I->isEHPad() || I->getType()->isTokenTy() ||
1143a8f5a829SArnold Schwaighofer                   I->isSwiftError())
11441c232f9bSPhilip Reames                 continue;
11451c232f9bSPhilip Reames 
11461c232f9bSPhilip Reames               outs() << "Checking instruction: " << *I;
11471c232f9bSPhilip Reames               std::unique_ptr<Module> M =
11481c232f9bSPhilip Reames                   BD.deleteInstructionFromProgram(&*I, Simplification);
11491c232f9bSPhilip Reames 
11501c232f9bSPhilip Reames               // Find out if the pass still crashes on this pass...
11511c232f9bSPhilip Reames               if (TestFn(BD, M.get())) {
11521c232f9bSPhilip Reames                 // Yup, it does, we delete the old module, and continue trying
11531c232f9bSPhilip Reames                 // to reduce the testcase...
1154f6074ed9SRafael Espindola                 BD.setNewProgram(std::move(M));
11551c232f9bSPhilip Reames                 InstructionsToSkipBeforeDeleting = CurInstructionNum;
11561c232f9bSPhilip Reames                 goto TryAgain; // I wish I had a multi-level break here!
11571c232f9bSPhilip Reames               }
11581c232f9bSPhilip Reames             }
11591c232f9bSPhilip Reames           }
11601c232f9bSPhilip Reames 
11611c232f9bSPhilip Reames     if (InstructionsToSkipBeforeDeleting) {
11621c232f9bSPhilip Reames       InstructionsToSkipBeforeDeleting = 0;
11631c232f9bSPhilip Reames       goto TryAgain;
11641c232f9bSPhilip Reames     }
11651c232f9bSPhilip Reames 
11661c232f9bSPhilip Reames   } while (Simplification);
116729e8b8ceSFlorian Hahn 
116829e8b8ceSFlorian Hahn   // Attempt to drop metadata from instructions that does not contribute to the
116929e8b8ceSFlorian Hahn   // crash.
117029e8b8ceSFlorian Hahn   if (!BugpointIsInterrupted) {
117129e8b8ceSFlorian Hahn     std::vector<Instruction *> Insts;
117229e8b8ceSFlorian Hahn     for (Function &F : BD.getProgram())
117329e8b8ceSFlorian Hahn       for (Instruction &I : instructions(F))
117429e8b8ceSFlorian Hahn         Insts.push_back(&I);
117529e8b8ceSFlorian Hahn 
117629e8b8ceSFlorian Hahn     Expected<bool> Result =
117729e8b8ceSFlorian Hahn         ReduceCrashingMetadata(BD, TestFn).reduceList(Insts);
117829e8b8ceSFlorian Hahn     if (Error E = Result.takeError())
117929e8b8ceSFlorian Hahn       return E;
118029e8b8ceSFlorian Hahn   }
118129e8b8ceSFlorian Hahn 
11821c232f9bSPhilip Reames   BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");
11831c039155SJustin Bogner   return Error::success();
11841c232f9bSPhilip Reames }
11851c232f9bSPhilip Reames 
11861c232f9bSPhilip Reames /// DebugACrash - Given a predicate that determines whether a component crashes
11871c232f9bSPhilip Reames /// on a program, try to destructively reduce the program while still keeping
11881c232f9bSPhilip Reames /// the predicate true.
DebugACrash(BugDriver & BD,BugTester TestFn)118908d829daSVedant Kumar static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
11901c232f9bSPhilip Reames   // See if we can get away with nuking some of the global variable initializers
11911c232f9bSPhilip Reames   // in the program...
11921c232f9bSPhilip Reames   if (!NoGlobalRM)
11931c039155SJustin Bogner     if (Error E = ReduceGlobalInitializers(BD, TestFn))
11941c039155SJustin Bogner       return E;
119573a6bdd9SChris Lattner 
11961d080f24SChris Lattner   // Now try to reduce the number of functions in the module to something small.
1197fd72bed3SChris Lattner   std::vector<Function *> Functions;
1198f6074ed9SRafael Espindola   for (Function &F : BD.getProgram())
1199306d16e0SDuncan P. N. Exon Smith     if (!F.isDeclaration())
1200306d16e0SDuncan P. N. Exon Smith       Functions.push_back(&F);
120173a6bdd9SChris Lattner 
1202beb01faeSChris Lattner   if (Functions.size() > 1 && !BugpointIsInterrupted) {
1203ee05152cSDan Gohman     outs() << "\n*** Attempting to reduce the number of functions "
12041d080f24SChris Lattner               "in the testcase\n";
120573a6bdd9SChris Lattner 
12068bda4c49SChris Lattner     unsigned OldSize = Functions.size();
12071c039155SJustin Bogner     Expected<bool> Result =
12081c039155SJustin Bogner         ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);
12091c039155SJustin Bogner     if (Error E = Result.takeError())
12101c039155SJustin Bogner       return E;
121173a6bdd9SChris Lattner 
1212beb01faeSChris Lattner     if (Functions.size() < OldSize)
1213594994a3SRafael Espindola       BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");
1214514c02ebSChris Lattner   }
1215514c02ebSChris Lattner 
12166f06eda0SMatt Arsenault   if (!NoAttributeRM) {
1217274981ebSBrian Gesiak     // For each remaining function, try to reduce that function's attributes.
1218274981ebSBrian Gesiak     std::vector<std::string> FunctionNames;
1219274981ebSBrian Gesiak     for (Function &F : BD.getProgram())
1220adcd0268SBenjamin Kramer       FunctionNames.push_back(std::string(F.getName()));
1221274981ebSBrian Gesiak 
1222274981ebSBrian Gesiak     if (!FunctionNames.empty() && !BugpointIsInterrupted) {
12236f06eda0SMatt Arsenault       outs() << "\n*** Attempting to reduce the number of function attributes"
12246f06eda0SMatt Arsenault                 " in the testcase\n";
1225274981ebSBrian Gesiak 
1226274981ebSBrian Gesiak       unsigned OldSize = 0;
1227274981ebSBrian Gesiak       unsigned NewSize = 0;
1228274981ebSBrian Gesiak       for (std::string &Name : FunctionNames) {
1229274981ebSBrian Gesiak         Function *Fn = BD.getProgram().getFunction(Name);
123096551c9cSCraig Topper         assert(Fn && "Could not find function?");
1231274981ebSBrian Gesiak 
1232274981ebSBrian Gesiak         std::vector<Attribute> Attrs;
123380ea2bb5SArthur Eubanks         for (Attribute A : Fn->getAttributes().getFnAttrs())
1234274981ebSBrian Gesiak           Attrs.push_back(A);
1235274981ebSBrian Gesiak 
1236274981ebSBrian Gesiak         OldSize += Attrs.size();
1237274981ebSBrian Gesiak         Expected<bool> Result =
1238274981ebSBrian Gesiak           ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);
1239274981ebSBrian Gesiak         if (Error E = Result.takeError())
1240274981ebSBrian Gesiak           return E;
1241274981ebSBrian Gesiak 
1242274981ebSBrian Gesiak         NewSize += Attrs.size();
1243274981ebSBrian Gesiak       }
1244274981ebSBrian Gesiak 
1245274981ebSBrian Gesiak       if (OldSize < NewSize)
1246274981ebSBrian Gesiak         BD.EmitProgressBitcode(BD.getProgram(), "reduced-function-attributes");
1247274981ebSBrian Gesiak     }
12486f06eda0SMatt Arsenault   }
1249274981ebSBrian Gesiak 
1250271ca401SDaniel Berlin   // Attempt to change conditional branches into unconditional branches to
1251271ca401SDaniel Berlin   // eliminate blocks.
1252271ca401SDaniel Berlin   if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
1253271ca401SDaniel Berlin     std::vector<const BasicBlock *> Blocks;
1254f6074ed9SRafael Espindola     for (Function &F : BD.getProgram())
1255271ca401SDaniel Berlin       for (BasicBlock &BB : F)
1256271ca401SDaniel Berlin         Blocks.push_back(&BB);
1257271ca401SDaniel Berlin     unsigned OldSize = Blocks.size();
12581c039155SJustin Bogner     Expected<bool> Result =
12591c039155SJustin Bogner         ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks);
12601c039155SJustin Bogner     if (Error E = Result.takeError())
12611c039155SJustin Bogner       return E;
12621c039155SJustin Bogner     Result = ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks);
12631c039155SJustin Bogner     if (Error E = Result.takeError())
12641c039155SJustin Bogner       return E;
1265271ca401SDaniel Berlin     if (Blocks.size() < OldSize)
1266271ca401SDaniel Berlin       BD.EmitProgressBitcode(BD.getProgram(), "reduced-conditionals");
1267271ca401SDaniel Berlin   }
1268271ca401SDaniel Berlin 
1269f32939bbSChris Lattner   // Attempt to delete entire basic blocks at a time to speed up
1270f32939bbSChris Lattner   // convergence... this actually works by setting the terminator of the blocks
1271f32939bbSChris Lattner   // to a return instruction then running simplifycfg, which can potentially
1272f32939bbSChris Lattner   // shrinks the code dramatically quickly
1273f32939bbSChris Lattner   //
1274beb01faeSChris Lattner   if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
12758bda4c49SChris Lattner     std::vector<const BasicBlock *> Blocks;
1276f6074ed9SRafael Espindola     for (Function &F : BD.getProgram())
1277306d16e0SDuncan P. N. Exon Smith       for (BasicBlock &BB : F)
1278306d16e0SDuncan P. N. Exon Smith         Blocks.push_back(&BB);
12796ee6f739STorok Edwin     unsigned OldSize = Blocks.size();
12801c039155SJustin Bogner     Expected<bool> Result = ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks);
12811c039155SJustin Bogner     if (Error E = Result.takeError())
12821c039155SJustin Bogner       return E;
12836ee6f739STorok Edwin     if (Blocks.size() < OldSize)
1284594994a3SRafael Espindola       BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks");
1285d1e2aaefSChris Lattner   }
12860eb5ce94SChris Lattner 
12870c559f6dSSimon Pilgrim   if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
128860606266SDaniel Berlin     std::vector<const BasicBlock *> Blocks;
1289f6074ed9SRafael Espindola     for (Function &F : BD.getProgram())
129060606266SDaniel Berlin       for (BasicBlock &BB : F)
129160606266SDaniel Berlin         Blocks.push_back(&BB);
129260606266SDaniel Berlin     unsigned OldSize = Blocks.size();
12931c039155SJustin Bogner     Expected<bool> Result = ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks);
12941c039155SJustin Bogner     if (Error E = Result.takeError())
12951c039155SJustin Bogner       return E;
129660606266SDaniel Berlin     if (Blocks.size() < OldSize)
129760606266SDaniel Berlin       BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplifycfg");
129860606266SDaniel Berlin   }
129960606266SDaniel Berlin 
13006e090c91SNick Lewycky   // Attempt to delete instructions using bisection. This should help out nasty
13016e090c91SNick Lewycky   // cases with large basic blocks where the problem is at one end.
13021c232f9bSPhilip Reames   if (!BugpointIsInterrupted)
13031c039155SJustin Bogner     if (Error E = ReduceInsts(BD, TestFn))
13041c039155SJustin Bogner       return E;
130534ca831dSKeno Fischer 
1306e5428043SMichael Ilseman   // Attempt to strip debug info metadata.
1307e5428043SMichael Ilseman   auto stripMetadata = [&](std::function<bool(Module &)> strip) {
1308f6074ed9SRafael Espindola     std::unique_ptr<Module> M = CloneModule(BD.getProgram());
1309e5428043SMichael Ilseman     strip(*M);
1310e5428043SMichael Ilseman     if (TestFn(BD, M.get()))
1311f6074ed9SRafael Espindola       BD.setNewProgram(std::move(M));
1312e5428043SMichael Ilseman   };
1313e5428043SMichael Ilseman   if (!NoStripDebugInfo && !BugpointIsInterrupted) {
1314e5428043SMichael Ilseman     outs() << "\n*** Attempting to strip the debug info: ";
1315e5428043SMichael Ilseman     stripMetadata(StripDebugInfo);
1316e5428043SMichael Ilseman   }
1317e5428043SMichael Ilseman   if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {
1318e5428043SMichael Ilseman     outs() << "\n*** Attempting to strip the debug type info: ";
1319e5428043SMichael Ilseman     stripMetadata(stripNonLineTableDebugInfo);
1320e5428043SMichael Ilseman   }
1321e5428043SMichael Ilseman 
1322ac285cc9SPhilip Reames   if (!NoNamedMDRM) {
132334ca831dSKeno Fischer     if (!BugpointIsInterrupted) {
132434ca831dSKeno Fischer       // Try to reduce the amount of global metadata (particularly debug info),
132534ca831dSKeno Fischer       // by dropping global named metadata that anchors them
132634ca831dSKeno Fischer       outs() << "\n*** Attempting to remove named metadata: ";
132734ca831dSKeno Fischer       std::vector<std::string> NamedMDNames;
1328f6074ed9SRafael Espindola       for (auto &NamedMD : BD.getProgram().named_metadata())
132934ca831dSKeno Fischer         NamedMDNames.push_back(NamedMD.getName().str());
13301c039155SJustin Bogner       Expected<bool> Result =
13311c039155SJustin Bogner           ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);
13321c039155SJustin Bogner       if (Error E = Result.takeError())
13331c039155SJustin Bogner         return E;
133434ca831dSKeno Fischer     }
133534ca831dSKeno Fischer 
133634ca831dSKeno Fischer     if (!BugpointIsInterrupted) {
133734ca831dSKeno Fischer       // Now that we quickly dropped all the named metadata that doesn't
133834ca831dSKeno Fischer       // contribute to the crash, bisect the operands of the remaining ones
133934ca831dSKeno Fischer       std::vector<const MDNode *> NamedMDOps;
1340f6074ed9SRafael Espindola       for (auto &NamedMD : BD.getProgram().named_metadata())
1341256df863SKeno Fischer         for (auto op : NamedMD.operands())
1342256df863SKeno Fischer           NamedMDOps.push_back(op);
13431c039155SJustin Bogner       Expected<bool> Result =
13441c039155SJustin Bogner           ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps);
13451c039155SJustin Bogner       if (Error E = Result.takeError())
13461c039155SJustin Bogner         return E;
134734ca831dSKeno Fischer     }
1348ac285cc9SPhilip Reames     BD.EmitProgressBitcode(BD.getProgram(), "reduced-named-md");
134934ca831dSKeno Fischer   }
135034ca831dSKeno Fischer 
1351514c02ebSChris Lattner   // Try to clean up the testcase by running funcresolve and globaldce...
1352beb01faeSChris Lattner   if (!BugpointIsInterrupted) {
1353ee05152cSDan Gohman     outs() << "\n*** Attempting to perform final cleanups: ";
1354f6074ed9SRafael Espindola     std::unique_ptr<Module> M = CloneModule(BD.getProgram());
1355b71251caSRafael Espindola     M = BD.performFinalCleanups(std::move(M), true);
1356514c02ebSChris Lattner 
1357514c02ebSChris Lattner     // Find out if the pass still crashes on the cleaned up program...
1358e84e7675SVedant Kumar     if (M && TestFn(BD, M.get()))
1359f6074ed9SRafael Espindola       BD.setNewProgram(
1360f6074ed9SRafael Espindola           std::move(M)); // Yup, it does, keep the reduced version...
1361beb01faeSChris Lattner   }
1362514c02ebSChris Lattner 
1363594994a3SRafael Espindola   BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");
1364514c02ebSChris Lattner 
13651c039155SJustin Bogner   return Error::success();
136673a6bdd9SChris Lattner }
1367960707c3SBrian Gaeke 
TestForOptimizerCrash(const BugDriver & BD,Module * M)1368d1c7ef4aSRafael Espindola static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {
1369f6074ed9SRafael Espindola   return BD.runPasses(*M, BD.getPassesToRun());
13708bda4c49SChris Lattner }
1371ead1dff0SChris Lattner 
13728bda4c49SChris Lattner /// debugOptimizerCrash - This method is called when some pass crashes on input.
13738bda4c49SChris Lattner /// It attempts to prune down the testcase to something reasonable, and figure
13748bda4c49SChris Lattner /// out exactly which pass is crashing.
13758bda4c49SChris Lattner ///
debugOptimizerCrash(const std::string & ID)13761c039155SJustin Bogner Error BugDriver::debugOptimizerCrash(const std::string &ID) {
1377ee05152cSDan Gohman   outs() << "\n*** Debugging optimizer crash!\n";
13788bda4c49SChris Lattner 
13798bda4c49SChris Lattner   // Reduce the list of passes which causes the optimizer to crash...
13801c039155SJustin Bogner   if (!BugpointIsInterrupted && !DontReducePassList) {
13811c039155SJustin Bogner     Expected<bool> Result = ReducePassList(*this).reduceList(PassesToRun);
13821c039155SJustin Bogner     if (Error E = Result.takeError())
13831c039155SJustin Bogner       return E;
13841c039155SJustin Bogner   }
13858bda4c49SChris Lattner 
1386ee05152cSDan Gohman   outs() << "\n*** Found crashing pass"
13878bda4c49SChris Lattner          << (PassesToRun.size() == 1 ? ": " : "es: ")
13886aa3c83fSMisha Brukman          << getPassesString(PassesToRun) << '\n';
13898bda4c49SChris Lattner 
1390f6074ed9SRafael Espindola   EmitProgressBitcode(*Program, ID);
13918bda4c49SChris Lattner 
139243a46f1cSFlorian Hahn   auto Res = DebugACrash(*this, TestForOptimizerCrash);
139343a46f1cSFlorian Hahn   if (Res || DontReducePassList)
139443a46f1cSFlorian Hahn     return Res;
139543a46f1cSFlorian Hahn   // Try to reduce the pass list again. This covers additional cases
139643a46f1cSFlorian Hahn   // we failed to reduce earlier, because of more complex pass dependencies
139743a46f1cSFlorian Hahn   // triggering the crash.
139843a46f1cSFlorian Hahn   auto SecondRes = ReducePassList(*this).reduceList(PassesToRun);
139943a46f1cSFlorian Hahn   if (Error E = SecondRes.takeError())
140043a46f1cSFlorian Hahn     return E;
140143a46f1cSFlorian Hahn   outs() << "\n*** Found crashing pass"
140243a46f1cSFlorian Hahn          << (PassesToRun.size() == 1 ? ": " : "es: ")
140343a46f1cSFlorian Hahn          << getPassesString(PassesToRun) << '\n';
140443a46f1cSFlorian Hahn 
140543a46f1cSFlorian Hahn   EmitProgressBitcode(getProgram(), "reduced-simplified");
140643a46f1cSFlorian Hahn   return Res;
14078bda4c49SChris Lattner }
14088bda4c49SChris Lattner 
TestForCodeGenCrash(const BugDriver & BD,Module * M)1409d1c7ef4aSRafael Espindola static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
1410f6074ed9SRafael Espindola   if (Error E = BD.compileProgram(*M)) {
14118f7d0199SSebastian Pop     if (VerboseErrors)
14121c039155SJustin Bogner       errs() << toString(std::move(E)) << "\n";
14131c039155SJustin Bogner     else {
14141c039155SJustin Bogner       consumeError(std::move(E));
1415d8db3760SDan Gohman       errs() << "<crash>\n";
14161c039155SJustin Bogner     }
14178bda4c49SChris Lattner     return true; // Tool is still crashing.
14188bda4c49SChris Lattner   }
14196ba630b0SNick Lewycky   errs() << '\n';
14206ba630b0SNick Lewycky   return false;
14218bda4c49SChris Lattner }
1422ead1dff0SChris Lattner 
1423ead1dff0SChris Lattner /// debugCodeGeneratorCrash - This method is called when the code generator
1424ead1dff0SChris Lattner /// crashes on an input.  It attempts to reduce the input as much as possible
1425ead1dff0SChris Lattner /// while still causing the code generator to crash.
debugCodeGeneratorCrash()14261c039155SJustin Bogner Error BugDriver::debugCodeGeneratorCrash() {
1427d8db3760SDan Gohman   errs() << "*** Debugging code generator crash!\n";
1428ead1dff0SChris Lattner 
14291c039155SJustin Bogner   return DebugACrash(*this, TestForCodeGenCrash);
1430ead1dff0SChris Lattner }
1431