llvm.org GIT mirror llvm / 11e0c31
[bugpoint] Add a named metadata (+their operands) reducer Summary: We frequently run bugpoint on a linked module that consists of all modules we create while jitting the julia standard library. This module has a very large number of compile units (10000+) in `llvm.dbg.cu`, which didn't get reduced at all, requiring manual post processing. This is an attempt to have bugpoint go through and attempt to reduce the number of global named metadata nodes as well as their operands, to cut down the number of roots for such metadata. Reviewers: dexonsmith, reames, pete Subscribers: pete, dexonsmith, reames, llvm-commits Differential Revision: http://reviews.llvm.org/D14043 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252247 91177308-0d34-0410-b5e6-96231b3b80d8 Keno Fischer 3 years ago
3 changed file(s) with 252 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
0 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null
1 ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
2 ; RUN-DISABLE: bugpoint -disable-namedmd-remove -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null
3 ; RUN-DISABLE: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
4 ; REQUIRES: loadable_module
5
6 ; CHECK: !llvm.dbg.cu = !{![[FIRST:[0-9]+]], ![[SECOND:[0-9]+]]}
7 ; CHECK-DISABLE: !llvm.dbg.cu = !{![[FIRST:[0-9]+]], ![[SECOND:[0-9]+]],
8 ; CHECK-DISABLE-SAME: ![[THIRD:[0-9]+]], ![[FOURTH:[0-9]+]], ![[FIFTH:[0-9]+]]}
9 !llvm.dbg.cu = !{!0, !1, !2, !3, !4, !5}
10 ; CHECK-NOT: !named
11 ; CHECK-DISABLE: !named
12 !named = !{!0, !1, !2, !3, !4, !5}
13 ; CHECK: !llvm.module.flags = !{![[DIVERSION:[0-9]+]]}
14 !llvm.module.flags = !{!6, !7}
15
16 ; CHECK-DAG: ![[FIRST]] = distinct !DICompileUnit(language: DW_LANG_Julia,
17 ; CHECK-DAG: ![[SECOND]] = distinct !DICompileUnit(language: DW_LANG_Julia,
18 ; CHECK-DAG: ![[DIVERSION]] = !{i32 2, !"Debug Info Version", i32 3}
19 ; CHECK-DAG: !DIFile(filename: "a", directory: "b")
20
21 ; 4 nodes survive. Due to renumbering !4 should not exist
22 ; CHECK-NOT: !4
23
24 !0 = distinct !DICompileUnit(language: DW_LANG_Julia,
25 file: !8)
26 !1 = distinct !DICompileUnit(language: DW_LANG_Julia,
27 file: !8)
28 !2 = distinct !DICompileUnit(language: DW_LANG_Julia,
29 file: !8)
30 !3 = distinct !DICompileUnit(language: DW_LANG_Julia,
31 file: !8)
32 !4 = distinct !DICompileUnit(language: DW_LANG_Julia,
33 file: !8)
34 !5 = distinct !DICompileUnit(language: DW_LANG_Julia,
35 file: !8)
36 !6 = !{i32 2, !"Dwarf Version", i32 2}
37 !7 = !{i32 2, !"Debug Info Version", i32 3}
38 !8 = !DIFile(filename: "a", directory: "b")
1414 #include "ListReducer.h"
1515 #include "ToolRunner.h"
1616 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/ADT/StringSet.h"
1718 #include "llvm/IR/CFG.h"
1819 #include "llvm/IR/Constants.h"
1920 #include "llvm/IR/DerivedTypes.h"
4849 DontReducePassList("disable-pass-list-reduction",
4950 cl::desc("Skip pass list reduction steps"),
5051 cl::init(false));
52
53 cl::opt NoNamedMDRM("disable-namedmd-remove",
54 cl::desc("Do not remove global named metadata"),
55 cl::init(false));
5156 }
5257
5358 namespace llvm {
496501 return false;
497502 }
498503
504 namespace {
505 // Reduce the list of Named Metadata nodes. We keep this as a list of
506 // names to avoid having to convert back and forth every time.
507 class ReduceCrashingNamedMD : public ListReducer {
508 BugDriver &BD;
509 bool (*TestFn)(const BugDriver &, Module *);
510
511 public:
512 ReduceCrashingNamedMD(BugDriver &bd,
513 bool (*testFn)(const BugDriver &, Module *))
514 : BD(bd), TestFn(testFn) {}
515
516 TestResult doTest(std::vector &Prefix,
517 std::vector &Kept,
518 std::string &Error) override {
519 if (!Kept.empty() && TestNamedMDs(Kept))
520 return KeepSuffix;
521 if (!Prefix.empty() && TestNamedMDs(Prefix))
522 return KeepPrefix;
523 return NoFailure;
524 }
525
526 bool TestNamedMDs(std::vector &NamedMDs);
527 };
528 }
529
530 bool ReduceCrashingNamedMD::TestNamedMDs(std::vector &NamedMDs) {
531
532 ValueToValueMapTy VMap;
533 Module *M = CloneModule(BD.getProgram(), VMap);
534
535 outs() << "Checking for crash with only these named metadata nodes:";
536 unsigned NumPrint = std::min(NamedMDs.size(), 10);
537 for (unsigned i = 0, e = NumPrint; i != e; ++i)
538 outs() << " " << NamedMDs[i];
539 if (NumPrint < NamedMDs.size())
540 outs() << "... <" << NamedMDs.size() << " total>";
541 outs() << ": ";
542
543 // Make a StringMap for faster lookup
544 StringSet<> Names;
545 for (const std::string &Name : NamedMDs)
546 Names.insert(Name);
547
548 // First collect all the metadata to delete in a vector, then
549 // delete them all at once to avoid invalidating the iterator
550 std::vector ToDelete;
551 ToDelete.reserve(M->named_metadata_size() - Names.size());
552 for (auto &NamedMD : M->named_metadata())
553 if (!Names.count(NamedMD.getName()))
554 ToDelete.push_back(&NamedMD);
555
556 for (auto *NamedMD : ToDelete)
557 NamedMD->eraseFromParent();
558
559 // Verify that this is still valid.
560 legacy::PassManager Passes;
561 Passes.add(createVerifierPass());
562 Passes.run(*M);
563
564 // Try running on the hacked up program...
565 if (TestFn(BD, M)) {
566 BD.setNewProgram(M); // It crashed, keep the trimmed version...
567 return true;
568 }
569 delete M; // It didn't crash, try something else.
570 return false;
571 }
572
573 namespace {
574 // Reduce the list of operands to named metadata nodes
575 class ReduceCrashingNamedMDOps : public ListReducer {
576 BugDriver &BD;
577 bool (*TestFn)(const BugDriver &, Module *);
578
579 public:
580 ReduceCrashingNamedMDOps(BugDriver &bd,
581 bool (*testFn)(const BugDriver &, Module *))
582 : BD(bd), TestFn(testFn) {}
583
584 TestResult doTest(std::vector &Prefix,
585 std::vector &Kept,
586 std::string &Error) override {
587 if (!Kept.empty() && TestNamedMDOps(Kept))
588 return KeepSuffix;
589 if (!Prefix.empty() && TestNamedMDOps(Prefix))
590 return KeepPrefix;
591 return NoFailure;
592 }
593
594 bool TestNamedMDOps(std::vector &NamedMDOps);
595 };
596 }
597
598 bool ReduceCrashingNamedMDOps::TestNamedMDOps(
599 std::vector &NamedMDOps) {
600 // Convert list to set for fast lookup...
601 SmallPtrSet OldMDNodeOps;
602 for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) {
603 OldMDNodeOps.insert(NamedMDOps[i]);
604 }
605
606 outs() << "Checking for crash with only " << OldMDNodeOps.size();
607 if (OldMDNodeOps.size() == 1)
608 outs() << " named metadata operand: ";
609 else
610 outs() << " named metadata operands: ";
611
612 ValueToValueMapTy VMap;
613 Module *M = CloneModule(BD.getProgram(), VMap);
614
615 // This is a little wasteful. In the future it might be good if we could have
616 // these dropped during cloning.
617 for (auto &NamedMD : BD.getProgram()->named_metadata()) {
618 // Drop the old one and create a new one
619 M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
620 NamedMDNode *NewNamedMDNode =
621 M->getOrInsertNamedMetadata(NamedMD.getName());
622 for (MDNode *op : NamedMD.operands())
623 if (OldMDNodeOps.count(op))
624 NewNamedMDNode->addOperand(cast(MapMetadata(op, VMap)));
625 }
626
627 // Verify that this is still valid.
628 legacy::PassManager Passes;
629 Passes.add(createVerifierPass());
630 Passes.run(*M);
631
632 // Try running on the hacked up program...
633 if (TestFn(BD, M)) {
634 // Make sure to use instruction pointers that point into the now-current
635 // module, and that they don't include any deleted blocks.
636 NamedMDOps.clear();
637 for (const MDNode *Node : OldMDNodeOps)
638 NamedMDOps.push_back(cast(VMap.MD()[Node].get()));
639
640 BD.setNewProgram(M); // It crashed, keep the trimmed version...
641 return true;
642 }
643 delete M; // It didn't crash, try something else.
644 return false;
645 }
646
499647 /// DebugACrash - Given a predicate that determines whether a component crashes
500648 /// on a program, try to destructively reduce the program while still keeping
501649 /// the predicate true.
660808 }
661809
662810 } while (Simplification);
811
812 if (!NoNamedMDRM) {
813 BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");
814
815 if (!BugpointIsInterrupted) {
816 // Try to reduce the amount of global metadata (particularly debug info),
817 // by dropping global named metadata that anchors them
818 outs() << "\n*** Attempting to remove named metadata: ";
819 std::vector NamedMDNames;
820 for (auto &NamedMD : BD.getProgram()->named_metadata())
821 NamedMDNames.push_back(NamedMD.getName().str());
822 ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames, Error);
823 }
824
825 if (!BugpointIsInterrupted) {
826 // Now that we quickly dropped all the named metadata that doesn't
827 // contribute to the crash, bisect the operands of the remaining ones
828 std::vector NamedMDOps;
829 for (auto &NamedMD : BD.getProgram()->named_metadata())
830 NamedMDOps.insert(NamedMDOps.end(), NamedMD.op_begin(),
831 NamedMD.op_end());
832 ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps, Error);
833 }
834 }
835
663836 ExitLoops:
664837
665838 // Try to clean up the testcase by running funcresolve and globaldce...
7575
7676 namespace {
7777 /// CrashOnDeclFunc - This pass is used to test bugpoint. It intentionally
78 /// crash if the module has an undefined function (ie a function that is
79 /// defined in an external module).
80 class CrashOnDeclFunc : public ModulePass {
81 public:
82 static char ID; // Pass ID, replacement for typeid
83 CrashOnDeclFunc() : ModulePass(ID) {}
84 private:
85 bool runOnModule(Module &M) override {
86 for (auto &F : M.functions()) {
87 if (F.isDeclaration())
88 abort();
89 }
90 return false;
78 /// crashes if the module has an undefined function (ie a function that is
79 /// defined in an external module).
80 class CrashOnDeclFunc : public ModulePass {
81 public:
82 static char ID; // Pass ID, replacement for typeid
83 CrashOnDeclFunc() : ModulePass(ID) {}
84
85 private:
86 bool runOnModule(Module &M) override {
87 for (auto &F : M.functions()) {
88 if (F.isDeclaration())
89 abort();
9190 }
91 return false;
92 }
9293 };
9394 }
9495
9697 static RegisterPass
9798 Z("bugpoint-crash-decl-funcs",
9899 "BugPoint Test Pass - Intentionally crash on declared functions");
100
101 #include
102 namespace {
103 /// CrashOnOneCU - This pass is used to test bugpoint. It intentionally
104 /// crashes if the Module has two or more compile units
105 class CrashOnTooManyCUs : public ModulePass {
106 public:
107 static char ID;
108 CrashOnTooManyCUs() : ModulePass(ID) {}
109
110 private:
111 bool runOnModule(Module &M) override {
112 NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
113 if (!CU_Nodes)
114 return false;
115 if (CU_Nodes->getNumOperands() >= 2)
116 abort();
117 return false;
118 }
119 };
120 }
121
122 char CrashOnTooManyCUs::ID = 0;
123 static RegisterPass
124 A("bugpoint-crash-too-many-cus",
125 "BugPoint Test Pass - Intentionally crash on too many CUs");