llvm.org GIT mirror llvm / 3d72b70
Split the SimplifyCFG pass into two variants. The first variant contains all current transformations except transforming switches into lookup tables. The second variant contains all current transformations. The switch-to-lookup-table conversion results in code that is more difficult to analyze and optimize by other passes. Most importantly, it can inhibit Dead Code Elimination. As such it is often beneficial to only apply this transformation very late. A common example is inlining, which can often result in range restrictions for the switch expression. Changes in execution time according to LNT: SingleSource/Benchmarks/Misc/fp-convert +3.03% MultiSource/Benchmarks/ASC_Sequoia/CrystalMk/CrystalMk -11.20% MultiSource/Benchmarks/Olden/perimeter/perimeter -10.43% and a couple of smaller changes. For perimeter it also results 2.6% a smaller binary. Differential Revision: https://reviews.llvm.org/D30333 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298799 91177308-0d34-0410-b5e6-96231b3b80d8 Joerg Sonnenberger 2 years ago
17 changed file(s) with 117 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
8585 void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&);
8686 void initializeCFGPrinterLegacyPassPass(PassRegistry&);
8787 void initializeCFGSimplifyPassPass(PassRegistry&);
88 void initializeLateCFGSimplifyPassPass(PassRegistry&);
8889 void initializeCFGViewerLegacyPassPass(PassRegistry&);
8990 void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
9091 void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
7474 (void) llvm::createCallGraphDOTPrinterPass();
7575 (void) llvm::createCallGraphViewerPass();
7676 (void) llvm::createCFGSimplificationPass();
77 (void) llvm::createLateCFGSimplificationPass();
7778 (void) llvm::createCFLAndersAAWrapperPass();
7879 (void) llvm::createCFLSteensAAWrapperPass();
7980 (void) llvm::createStructurizeCFGPass();
2626 /// by the rest of the mid-level optimizer.
2727 class SimplifyCFGPass : public PassInfoMixin {
2828 int BonusInstThreshold;
29 bool LateSimplifyCFG;
2930
3031 public:
31 /// \brief Construct a pass with the default thresholds.
32 /// \brief Construct a pass with the default thresholds
33 /// and switch optimizations.
3234 SimplifyCFGPass();
3335
34 /// \brief Construct a pass with a specific bonus threshold.
35 SimplifyCFGPass(int BonusInstThreshold);
36 /// \brief Construct a pass with a specific bonus threshold
37 /// and optional switch optimizations.
38 SimplifyCFGPass(int BonusInstThreshold, bool LateSimplifyCFG);
3639
3740 /// \brief Run the pass over the function.
3841 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
261261
262262 //===----------------------------------------------------------------------===//
263263 //
264 // LateCFGSimplification - Like CFGSimplification, but may also
265 // convert switches to lookup tables.
266 //
267 FunctionPass *createLateCFGSimplificationPass(
268 int Threshold = -1, std::function Ftor = nullptr);
269
270 //===----------------------------------------------------------------------===//
271 //
264272 // FlattenCFG - flatten CFG, reduce number of conditional branches by using
265273 // parallel-and and parallel-or mode, etc...
266274 //
141141 /// eliminate.
142142 bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
143143 unsigned BonusInstThreshold, AssumptionCache *AC = nullptr,
144 SmallPtrSetImpl *LoopHeaders = nullptr);
144 SmallPtrSetImpl *LoopHeaders = nullptr,
145 bool LateSimplifyCFG = false);
145146
146147 /// This function is used to flatten a CFG. For example, it uses parallel-and
147148 /// and parallel-or mode to collapse if-conditions and merge if-regions with
4242
4343 /** See llvm::createCFGSimplificationPass function. */
4444 void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
45
46 /** See llvm::createLateCFGSimplificationPass function. */
47 void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM);
4548
4649 /** See llvm::createDeadStoreEliminationPass function. */
4750 void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM);
140140 initializeMemCpyOptLegacyPassPass(R);
141141 initializeDCELegacyPassPass(R);
142142 initializeCFGSimplifyPassPass(R);
143 initializeLateCFGSimplifyPassPass(R);
143144 }
144145
145146 void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) {
630630 }
631631
632632 addExtensionsToPM(EP_Peephole, MPM);
633 MPM.add(createCFGSimplificationPass());
633 MPM.add(createLateCFGSimplificationPass()); // Switches to lookup tables
634634 addInstructionCombiningPass(MPM);
635635
636636 if (!DisableUnrollLoops) {
8080 initializeIPSCCPLegacyPassPass(Registry);
8181 initializeSROALegacyPassPass(Registry);
8282 initializeCFGSimplifyPassPass(Registry);
83 initializeLateCFGSimplifyPassPass(Registry);
8384 initializeStructurizeCFGPass(Registry);
8485 initializeSinkingLegacyPassPass(Registry);
8586 initializeTailCallElimPass(Registry);
116117 unwrap(PM)->add(createCFGSimplificationPass());
117118 }
118119
120 void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM) {
121 unwrap(PM)->add(createLateCFGSimplificationPass());
122 }
123
119124 void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM) {
120125 unwrap(PM)->add(createDeadStoreEliminationPass());
121126 }
129129 /// iterating until no more changes are made.
130130 static bool iterativelySimplifyCFG(Function &F, const TargetTransformInfo &TTI,
131131 AssumptionCache *AC,
132 unsigned BonusInstThreshold) {
132 unsigned BonusInstThreshold,
133 bool LateSimplifyCFG) {
133134 bool Changed = false;
134135 bool LocalChange = true;
135136
144145
145146 // Loop over all of the basic blocks and remove them if they are unneeded.
146147 for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {
147 if (SimplifyCFG(&*BBIt++, TTI, BonusInstThreshold, AC, &LoopHeaders)) {
148 if (SimplifyCFG(&*BBIt++, TTI, BonusInstThreshold, AC, &LoopHeaders, LateSimplifyCFG)) {
148149 LocalChange = true;
149150 ++NumSimpl;
150151 }
155156 }
156157
157158 static bool simplifyFunctionCFG(Function &F, const TargetTransformInfo &TTI,
158 AssumptionCache *AC, int BonusInstThreshold) {
159 AssumptionCache *AC, int BonusInstThreshold,
160 bool LateSimplifyCFG) {
159161 bool EverChanged = removeUnreachableBlocks(F);
160162 EverChanged |= mergeEmptyReturnBlocks(F);
161 EverChanged |= iterativelySimplifyCFG(F, TTI, AC, BonusInstThreshold);
163 EverChanged |= iterativelySimplifyCFG(F, TTI, AC, BonusInstThreshold,
164 LateSimplifyCFG);
162165
163166 // If neither pass changed anything, we're done.
164167 if (!EverChanged) return false;
172175 return true;
173176
174177 do {
175 EverChanged = iterativelySimplifyCFG(F, TTI, AC, BonusInstThreshold);
178 EverChanged = iterativelySimplifyCFG(F, TTI, AC, BonusInstThreshold,
179 LateSimplifyCFG);
176180 EverChanged |= removeUnreachableBlocks(F);
177181 } while (EverChanged);
178182
180184 }
181185
182186 SimplifyCFGPass::SimplifyCFGPass()
183 : BonusInstThreshold(UserBonusInstThreshold) {}
184
185 SimplifyCFGPass::SimplifyCFGPass(int BonusInstThreshold)
186 : BonusInstThreshold(BonusInstThreshold) {}
187 : BonusInstThreshold(UserBonusInstThreshold),
188 LateSimplifyCFG(true) {}
189
190 SimplifyCFGPass::SimplifyCFGPass(int BonusInstThreshold, bool LateSimplifyCFG)
191 : BonusInstThreshold(BonusInstThreshold),
192 LateSimplifyCFG(LateSimplifyCFG) {}
187193
188194 PreservedAnalyses SimplifyCFGPass::run(Function &F,
189195 FunctionAnalysisManager &AM) {
190196 auto &TTI = AM.getResult(F);
191197 auto &AC = AM.getResult(F);
192198
193 if (!simplifyFunctionCFG(F, TTI, &AC, BonusInstThreshold))
199 if (!simplifyFunctionCFG(F, TTI, &AC, BonusInstThreshold, LateSimplifyCFG))
194200 return PreservedAnalyses::all();
195201 PreservedAnalyses PA;
196202 PA.preserve();
198204 }
199205
200206 namespace {
201 struct CFGSimplifyPass : public FunctionPass {
202 static char ID; // Pass identification, replacement for typeid
207 struct BaseCFGSimplifyPass : public FunctionPass {
203208 unsigned BonusInstThreshold;
204209 std::function PredicateFtor;
205
206 CFGSimplifyPass(int T = -1,
207 std::function Ftor = nullptr)
208 : FunctionPass(ID), PredicateFtor(std::move(Ftor)) {
210 bool LateSimplifyCFG;
211
212 BaseCFGSimplifyPass(int T, bool LateSimplifyCFG,
213 std::function Ftor,
214 char &ID)
215 : FunctionPass(ID), PredicateFtor(std::move(Ftor)),
216 LateSimplifyCFG(LateSimplifyCFG) {
209217 BonusInstThreshold = (T == -1) ? UserBonusInstThreshold : unsigned(T);
210 initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
211218 }
212219 bool runOnFunction(Function &F) override {
213220 if (skipFunction(F) || (PredicateFtor && !PredicateFtor(F)))
217224 &getAnalysis().getAssumptionCache(F);
218225 const TargetTransformInfo &TTI =
219226 getAnalysis().getTTI(F);
220 return simplifyFunctionCFG(F, TTI, AC, BonusInstThreshold);
227 return simplifyFunctionCFG(F, TTI, AC, BonusInstThreshold, LateSimplifyCFG);
221228 }
222229
223230 void getAnalysisUsage(AnalysisUsage &AU) const override {
224231 AU.addRequired();
225232 AU.addRequired();
226233 AU.addPreserved();
234 }
235 };
236
237 struct CFGSimplifyPass : public BaseCFGSimplifyPass {
238 static char ID; // Pass identification, replacement for typeid
239
240 CFGSimplifyPass(int T = -1,
241 std::function Ftor = nullptr)
242 : BaseCFGSimplifyPass(T, false, Ftor, ID) {
243 initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
244 }
245 };
246
247 struct LateCFGSimplifyPass : public BaseCFGSimplifyPass {
248 static char ID; // Pass identification, replacement for typeid
249
250 LateCFGSimplifyPass(int T = -1,
251 std::function Ftor = nullptr)
252 : BaseCFGSimplifyPass(T, true, Ftor, ID) {
253 initializeLateCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
227254 }
228255 };
229256 }
236263 INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
237264 false)
238265
266 char LateCFGSimplifyPass::ID = 0;
267 INITIALIZE_PASS_BEGIN(LateCFGSimplifyPass, "latesimplifycfg",
268 "Simplify the CFG more aggressively", false, false)
269 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
270 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
271 INITIALIZE_PASS_END(LateCFGSimplifyPass, "latesimplifycfg",
272 "Simplify the CFG more aggressively", false, false)
273
239274 // Public interface to the CFGSimplification pass
240275 FunctionPass *
241276 llvm::createCFGSimplificationPass(int Threshold,
277 std::function Ftor) {
278 return new CFGSimplifyPass(Threshold, std::move(Ftor));
279 }
280
281 // Public interface to the LateCFGSimplification pass
282 FunctionPass *
283 llvm::createLateCFGSimplificationPass(int Threshold,
242284 std::function Ftor) {
243 return new CFGSimplifyPass(Threshold, std::move(Ftor));
244 }
285 return new LateCFGSimplifyPass(Threshold, std::move(Ftor));
286 }
169169 unsigned BonusInstThreshold;
170170 AssumptionCache *AC;
171171 SmallPtrSetImpl *LoopHeaders;
172 // See comments in SimplifyCFGOpt::SimplifySwitch.
173 bool LateSimplifyCFG;
172174 Value *isValueEqualityComparison(TerminatorInst *TI);
173175 BasicBlock *GetValueEqualityComparisonCases(
174176 TerminatorInst *TI, std::vector &Cases);
192194 public:
193195 SimplifyCFGOpt(const TargetTransformInfo &TTI, const DataLayout &DL,
194196 unsigned BonusInstThreshold, AssumptionCache *AC,
195 SmallPtrSetImpl *LoopHeaders)
197 SmallPtrSetImpl *LoopHeaders,
198 bool LateSimplifyCFG)
196199 : TTI(TTI), DL(DL), BonusInstThreshold(BonusInstThreshold), AC(AC),
197 LoopHeaders(LoopHeaders) {}
200 LoopHeaders(LoopHeaders), LateSimplifyCFG(LateSimplifyCFG) {}
198201
199202 bool run(BasicBlock *BB);
200203 };
55615564 if (ForwardSwitchConditionToPHI(SI))
55625565 return SimplifyCFG(BB, TTI, BonusInstThreshold, AC) | true;
55635566
5564 if (SwitchToLookupTable(SI, Builder, DL, TTI))
5567 // The conversion from switch to lookup tables results in difficult
5568 // to analyze code and makes pruning branches much harder.
5569 // This is a problem of the switch expression itself can still be
5570 // restricted as a result of inlining or CVP. There only apply this
5571 // transformation during late steps of the optimisation chain.
5572 if (LateSimplifyCFG && SwitchToLookupTable(SI, Builder, DL, TTI))
55655573 return SimplifyCFG(BB, TTI, BonusInstThreshold, AC) | true;
55665574
55675575 if (ReduceSwitchRange(SI, Builder, DL, TTI))
60206028 ///
60216029 bool llvm::SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
60226030 unsigned BonusInstThreshold, AssumptionCache *AC,
6023 SmallPtrSetImpl *LoopHeaders) {
6031 SmallPtrSetImpl *LoopHeaders,
6032 bool LateSimplifyCFG) {
60246033 return SimplifyCFGOpt(TTI, BB->getModule()->getDataLayout(),
6025 BonusInstThreshold, AC, LoopHeaders)
6034 BonusInstThreshold, AC, LoopHeaders, LateSimplifyCFG)
60266035 .run(BB);
60276036 }
None ; RUN: opt -S -simplifycfg -mtriple=arm -relocation-model=static < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
1 ; RUN: opt -S -simplifycfg -mtriple=arm -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
2 ; RUN: opt -S -simplifycfg -mtriple=arm -relocation-model=ropi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
3 ; RUN: opt -S -simplifycfg -mtriple=arm -relocation-model=rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
4 ; RUN: opt -S -simplifycfg -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
0 ; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=static < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
1 ; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
2 ; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=ropi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
3 ; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
4 ; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
55
66 ; CHECK: @{{.*}} = private unnamed_addr constant [3 x i32] [i32 1234, i32 5678, i32 15532]
77 ; ENABLE: @{{.*}} = private unnamed_addr constant [3 x i32*] [i32* @c1, i32* @c2, i32* @c3]
None ; RUN: opt -simplifycfg -S %s | FileCheck %s
0 ; RUN: opt -latesimplifycfg -S %s | FileCheck %s
11 ; rdar://15268442
22
33 target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
None ; RUN: opt -S -simplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
0 ; RUN: opt -S -latesimplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
11 ; rdar://17887153
22 target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
33 target triple = "x86_64-apple-darwin12.0.0"
None ; RUN: opt -S -simplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
0 ; RUN: opt -S -latesimplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
11 ; rdar://17735071
22 target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
33 target triple = "x86_64-apple-darwin12.0.0"
None ; RUN: opt < %s -simplifycfg -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
0 ; RUN: opt < %s -latesimplifycfg -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
11
22 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
33 target triple = "x86_64-unknown-linux-gnu"
11771177 ret i32 %retval.0
11781178 ; CHECK-LABEL: @reuse_cmp2(
11791179 ; CHECK: entry:
1180 ; CHECK-NEXT: %switch.tableidx = sub i32 %x, 0
1181 ; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %switch.tableidx, 4
1180 ; CHECK-NEXT: %switch = icmp ult i32 %x, 4
1181 ; CHECK-NEXT: %x. = select i1 %switch, i32 %x, i32 4
1182 ; CHECK-NEXT: [[C:%.+]] = icmp ne i32 %x., 4
11821183 ; CHECK: [[R:%.+]] = select i1 [[C]], i32 {{.*}}, i32 100
11831184 ; CHECK-NEXT: ret i32 [[R]]
11841185 }
None ; RUN: opt < %s -simplifycfg -S | FileCheck %s
0 ; RUN: opt < %s -latesimplifycfg -S | FileCheck %s
11
22 target datalayout = "e-n32"
33