1 | //===- DeltaManager.cpp - Runs Delta Passes to reduce Input ---------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file calls each specialized Delta pass in order to reduce the input IR |
10 | // file. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "DeltaManager.h" |
15 | #include "DeltaPass.h" |
16 | #include "TestRunner.h" |
17 | #include "deltas/ReduceAliases.h" |
18 | #include "deltas/ReduceArguments.h" |
19 | #include "deltas/ReduceAttributes.h" |
20 | #include "deltas/ReduceBasicBlocks.h" |
21 | #include "deltas/ReduceDIMetadata.h" |
22 | #include "deltas/ReduceDbgRecords.h" |
23 | #include "deltas/ReduceDistinctMetadata.h" |
24 | #include "deltas/ReduceFunctionBodies.h" |
25 | #include "deltas/ReduceFunctions.h" |
26 | #include "deltas/ReduceGlobalObjects.h" |
27 | #include "deltas/ReduceGlobalValues.h" |
28 | #include "deltas/ReduceGlobalVarInitializers.h" |
29 | #include "deltas/ReduceGlobalVars.h" |
30 | #include "deltas/ReduceIRReferences.h" |
31 | #include "deltas/ReduceInstructionFlags.h" |
32 | #include "deltas/ReduceInstructionFlagsMIR.h" |
33 | #include "deltas/ReduceInstructions.h" |
34 | #include "deltas/ReduceInstructionsMIR.h" |
35 | #include "deltas/ReduceInvokes.h" |
36 | #include "deltas/ReduceMemoryOperations.h" |
37 | #include "deltas/ReduceMetadata.h" |
38 | #include "deltas/ReduceModuleData.h" |
39 | #include "deltas/ReduceOpcodes.h" |
40 | #include "deltas/ReduceOperandBundles.h" |
41 | #include "deltas/ReduceOperands.h" |
42 | #include "deltas/ReduceOperandsSkip.h" |
43 | #include "deltas/ReduceOperandsToArgs.h" |
44 | #include "deltas/ReduceRegisterDefs.h" |
45 | #include "deltas/ReduceRegisterMasks.h" |
46 | #include "deltas/ReduceRegisterUses.h" |
47 | #include "deltas/ReduceSpecialGlobals.h" |
48 | #include "deltas/ReduceTargetFeaturesAttr.h" |
49 | #include "deltas/ReduceUsingSimplifyCFG.h" |
50 | #include "deltas/ReduceValuesToReturn.h" |
51 | #include "deltas/ReduceVirtualRegisters.h" |
52 | #include "deltas/RunIRPasses.h" |
53 | #include "deltas/SimplifyInstructions.h" |
54 | #include "deltas/StripDebugInfo.h" |
55 | #include "llvm/ADT/SmallSet.h" |
56 | #include "llvm/Support/CommandLine.h" |
57 | |
58 | using namespace llvm; |
59 | |
60 | using SmallStringSet = SmallSet<StringRef, 8>; |
61 | |
62 | extern cl::OptionCategory LLVMReduceOptions; |
63 | static cl::list<std::string> |
64 | DeltaPasses("delta-passes" , |
65 | cl::desc("Delta passes to run, separated by commas. By " |
66 | "default, run all delta passes." ), |
67 | cl::cat(LLVMReduceOptions), cl::CommaSeparated); |
68 | |
69 | static cl::list<std::string> |
70 | SkipDeltaPasses("skip-delta-passes" , |
71 | cl::desc("Delta passes to not run, separated by commas. By " |
72 | "default, run all delta passes." ), |
73 | cl::cat(LLVMReduceOptions), cl::CommaSeparated); |
74 | |
75 | // Generate two separate Pass lists: IR_Passes and MIR_Passes |
76 | static const DeltaPass IR_Passes[] = { |
77 | #undef DELTA_PASS_IR |
78 | #undef DELTA_PASS_MIR |
79 | #define DELTA_PASS_IR(NAME, FUNC, DESC) {NAME, FUNC, DESC}, |
80 | #include "DeltaPasses.def" |
81 | #undef DELTA_PASS_IR |
82 | }; |
83 | |
84 | static const DeltaPass MIR_Passes[] = { |
85 | #undef DELTA_PASS_IR |
86 | #undef DELTA_PASS_MIR |
87 | #define DELTA_PASS_MIR(NAME, FUNC, DESC) {NAME, FUNC, DESC}, |
88 | #include "DeltaPasses.def" |
89 | #undef DELTA_PASS_MIR |
90 | }; |
91 | |
92 | static void runAllDeltaPasses(TestRunner &Tester, |
93 | const SmallStringSet &SkipPass) { |
94 | if (Tester.getProgram().isMIR()) { |
95 | for (const DeltaPass &Pass : MIR_Passes) { |
96 | if (!SkipPass.count(V: Pass.Name)) { |
97 | runDeltaPass(Test&: Tester, Pass); |
98 | } |
99 | } |
100 | } else { |
101 | for (const DeltaPass &Pass : IR_Passes) { |
102 | if (!SkipPass.count(V: Pass.Name)) { |
103 | runDeltaPass(Test&: Tester, Pass); |
104 | } |
105 | } |
106 | } |
107 | } |
108 | |
109 | static void runDeltaPassName(TestRunner &Tester, StringRef PassName) { |
110 | if (Tester.getProgram().isMIR()) { |
111 | for (const DeltaPass &Pass : MIR_Passes) { |
112 | if (PassName == Pass.Name) { |
113 | runDeltaPass(Test&: Tester, Pass); |
114 | return; |
115 | } |
116 | } |
117 | } else { |
118 | for (const DeltaPass &Pass : IR_Passes) { |
119 | if (PassName == Pass.Name) { |
120 | runDeltaPass(Test&: Tester, Pass); |
121 | return; |
122 | } |
123 | } |
124 | } |
125 | |
126 | // We should have errored on unrecognized passes before trying to run |
127 | // anything. |
128 | llvm_unreachable("unknown delta pass" ); |
129 | } |
130 | |
131 | void llvm::printDeltaPasses(raw_ostream &OS) { |
132 | OS << "Delta passes (pass to `--delta-passes=` as a comma separated list):\n" ; |
133 | OS << " IR:\n" ; |
134 | for (const DeltaPass &Pass : IR_Passes) { |
135 | OS << " " << Pass.Name << '\n'; |
136 | } |
137 | OS << " MIR:\n" ; |
138 | for (const DeltaPass &Pass : MIR_Passes) { |
139 | OS << " " << Pass.Name << '\n'; |
140 | } |
141 | } |
142 | |
143 | // Built a set of available delta passes. |
144 | static void collectPassNames(const TestRunner &Tester, |
145 | SmallStringSet &NameSet) { |
146 | for (const DeltaPass &Pass : MIR_Passes) { |
147 | NameSet.insert(V: Pass.Name); |
148 | } |
149 | for (const DeltaPass &Pass : IR_Passes) { |
150 | NameSet.insert(V: Pass.Name); |
151 | } |
152 | } |
153 | |
154 | /// Verify all requested or skipped passes are valid names, and return them in a |
155 | /// set. |
156 | static SmallStringSet handlePassList(const TestRunner &Tester, |
157 | const cl::list<std::string> &PassList) { |
158 | SmallStringSet AllPasses; |
159 | collectPassNames(Tester, NameSet&: AllPasses); |
160 | |
161 | SmallStringSet PassSet; |
162 | for (StringRef PassName : PassList) { |
163 | if (!AllPasses.count(V: PassName)) { |
164 | errs() << "unknown pass \"" << PassName << "\"\n" ; |
165 | exit(status: 1); |
166 | } |
167 | |
168 | PassSet.insert(V: PassName); |
169 | } |
170 | |
171 | return PassSet; |
172 | } |
173 | |
174 | void llvm::runDeltaPasses(TestRunner &Tester, int MaxPassIterations) { |
175 | uint64_t OldComplexity = Tester.getProgram().getComplexityScore(); |
176 | |
177 | SmallStringSet RunPassSet, SkipPassSet; |
178 | |
179 | if (!DeltaPasses.empty()) |
180 | RunPassSet = handlePassList(Tester, PassList: DeltaPasses); |
181 | |
182 | if (!SkipDeltaPasses.empty()) |
183 | SkipPassSet = handlePassList(Tester, PassList: SkipDeltaPasses); |
184 | |
185 | for (int Iter = 0; Iter < MaxPassIterations; ++Iter) { |
186 | if (DeltaPasses.empty()) { |
187 | runAllDeltaPasses(Tester, SkipPass: SkipPassSet); |
188 | } else { |
189 | for (StringRef PassName : DeltaPasses) { |
190 | if (!SkipPassSet.count(V: PassName)) |
191 | runDeltaPassName(Tester, PassName); |
192 | } |
193 | } |
194 | |
195 | uint64_t NewComplexity = Tester.getProgram().getComplexityScore(); |
196 | if (NewComplexity >= OldComplexity) |
197 | break; |
198 | OldComplexity = NewComplexity; |
199 | } |
200 | } |
201 | |