File: | llvm/lib/Transforms/Scalar/LoopDeletion.cpp |
Warning: | line 66, column 23 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- LoopDeletion.cpp - Dead Loop Deletion Pass ---------------===// | |||
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 implements the Dead Loop Deletion Pass. This pass is responsible | |||
10 | // for eliminating loops with non-infinite computable trip counts that have no | |||
11 | // side effects or volatile instructions, and do not contribute to the | |||
12 | // computation of the function's return value. | |||
13 | // | |||
14 | //===----------------------------------------------------------------------===// | |||
15 | ||||
16 | #include "llvm/Transforms/Scalar/LoopDeletion.h" | |||
17 | #include "llvm/ADT/SmallVector.h" | |||
18 | #include "llvm/ADT/Statistic.h" | |||
19 | #include "llvm/Analysis/GlobalsModRef.h" | |||
20 | #include "llvm/Analysis/LoopPass.h" | |||
21 | #include "llvm/Analysis/MemorySSA.h" | |||
22 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" | |||
23 | #include "llvm/IR/Dominators.h" | |||
24 | #include "llvm/IR/PatternMatch.h" | |||
25 | #include "llvm/InitializePasses.h" | |||
26 | #include "llvm/Transforms/Scalar.h" | |||
27 | #include "llvm/Transforms/Scalar/LoopPassManager.h" | |||
28 | #include "llvm/Transforms/Utils/LoopUtils.h" | |||
29 | ||||
30 | using namespace llvm; | |||
31 | ||||
32 | #define DEBUG_TYPE"loop-delete" "loop-delete" | |||
33 | ||||
34 | STATISTIC(NumDeleted, "Number of loops deleted")static llvm::Statistic NumDeleted = {"loop-delete", "NumDeleted" , "Number of loops deleted"}; | |||
35 | ||||
36 | enum class LoopDeletionResult { | |||
37 | Unmodified, | |||
38 | Modified, | |||
39 | Deleted, | |||
40 | }; | |||
41 | ||||
42 | static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B) { | |||
43 | if (A == LoopDeletionResult::Deleted || B == LoopDeletionResult::Deleted) | |||
44 | return LoopDeletionResult::Deleted; | |||
45 | if (A == LoopDeletionResult::Modified || B == LoopDeletionResult::Modified) | |||
46 | return LoopDeletionResult::Modified; | |||
47 | return LoopDeletionResult::Unmodified; | |||
48 | } | |||
49 | ||||
50 | /// Determines if a loop is dead. | |||
51 | /// | |||
52 | /// This assumes that we've already checked for unique exit and exiting blocks, | |||
53 | /// and that the code is in LCSSA form. | |||
54 | static bool isLoopDead(Loop *L, ScalarEvolution &SE, | |||
55 | SmallVectorImpl<BasicBlock *> &ExitingBlocks, | |||
56 | BasicBlock *ExitBlock, bool &Changed, | |||
57 | BasicBlock *Preheader) { | |||
58 | // Make sure that all PHI entries coming from the loop are loop invariant. | |||
59 | // Because the code is in LCSSA form, any values used outside of the loop | |||
60 | // must pass through a PHI in the exit block, meaning that this check is | |||
61 | // sufficient to guarantee that no loop-variant values are used outside | |||
62 | // of the loop. | |||
63 | bool AllEntriesInvariant = true; | |||
64 | bool AllOutgoingValuesSame = true; | |||
65 | if (!L->hasNoExitBlocks()) { | |||
66 | for (PHINode &P : ExitBlock->phis()) { | |||
| ||||
67 | Value *incoming = P.getIncomingValueForBlock(ExitingBlocks[0]); | |||
68 | ||||
69 | // Make sure all exiting blocks produce the same incoming value for the | |||
70 | // block. If there are different incoming values for different exiting | |||
71 | // blocks, then it is impossible to statically determine which value | |||
72 | // should be used. | |||
73 | AllOutgoingValuesSame = | |||
74 | all_of(makeArrayRef(ExitingBlocks).slice(1), [&](BasicBlock *BB) { | |||
75 | return incoming == P.getIncomingValueForBlock(BB); | |||
76 | }); | |||
77 | ||||
78 | if (!AllOutgoingValuesSame) | |||
79 | break; | |||
80 | ||||
81 | if (Instruction *I = dyn_cast<Instruction>(incoming)) | |||
82 | if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) { | |||
83 | AllEntriesInvariant = false; | |||
84 | break; | |||
85 | } | |||
86 | } | |||
87 | } | |||
88 | ||||
89 | if (Changed) | |||
90 | SE.forgetLoopDispositions(L); | |||
91 | ||||
92 | if (!AllEntriesInvariant || !AllOutgoingValuesSame) | |||
93 | return false; | |||
94 | ||||
95 | // Make sure that no instructions in the block have potential side-effects. | |||
96 | // This includes instructions that could write to memory, and loads that are | |||
97 | // marked volatile. | |||
98 | for (auto &I : L->blocks()) | |||
99 | if (any_of(*I, [](Instruction &I) { | |||
100 | return I.mayHaveSideEffects() && !I.isDroppable(); | |||
101 | })) | |||
102 | return false; | |||
103 | return true; | |||
104 | } | |||
105 | ||||
106 | /// This function returns true if there is no viable path from the | |||
107 | /// entry block to the header of \p L. Right now, it only does | |||
108 | /// a local search to save compile time. | |||
109 | static bool isLoopNeverExecuted(Loop *L) { | |||
110 | using namespace PatternMatch; | |||
111 | ||||
112 | auto *Preheader = L->getLoopPreheader(); | |||
113 | // TODO: We can relax this constraint, since we just need a loop | |||
114 | // predecessor. | |||
115 | assert(Preheader && "Needs preheader!")((Preheader && "Needs preheader!") ? static_cast<void > (0) : __assert_fail ("Preheader && \"Needs preheader!\"" , "/build/llvm-toolchain-snapshot-12~++20210125100614+2cdb34efdac5/llvm/lib/Transforms/Scalar/LoopDeletion.cpp" , 115, __PRETTY_FUNCTION__)); | |||
116 | ||||
117 | if (Preheader == &Preheader->getParent()->getEntryBlock()) | |||
118 | return false; | |||
119 | // All predecessors of the preheader should have a constant conditional | |||
120 | // branch, with the loop's preheader as not-taken. | |||
121 | for (auto *Pred: predecessors(Preheader)) { | |||
122 | BasicBlock *Taken, *NotTaken; | |||
123 | ConstantInt *Cond; | |||
124 | if (!match(Pred->getTerminator(), | |||
125 | m_Br(m_ConstantInt(Cond), Taken, NotTaken))) | |||
126 | return false; | |||
127 | if (!Cond->getZExtValue()) | |||
128 | std::swap(Taken, NotTaken); | |||
129 | if (Taken == Preheader) | |||
130 | return false; | |||
131 | } | |||
132 | assert(!pred_empty(Preheader) &&((!pred_empty(Preheader) && "Preheader should have predecessors at this point!" ) ? static_cast<void> (0) : __assert_fail ("!pred_empty(Preheader) && \"Preheader should have predecessors at this point!\"" , "/build/llvm-toolchain-snapshot-12~++20210125100614+2cdb34efdac5/llvm/lib/Transforms/Scalar/LoopDeletion.cpp" , 133, __PRETTY_FUNCTION__)) | |||
133 | "Preheader should have predecessors at this point!")((!pred_empty(Preheader) && "Preheader should have predecessors at this point!" ) ? static_cast<void> (0) : __assert_fail ("!pred_empty(Preheader) && \"Preheader should have predecessors at this point!\"" , "/build/llvm-toolchain-snapshot-12~++20210125100614+2cdb34efdac5/llvm/lib/Transforms/Scalar/LoopDeletion.cpp" , 133, __PRETTY_FUNCTION__)); | |||
134 | // All the predecessors have the loop preheader as not-taken target. | |||
135 | return true; | |||
136 | } | |||
137 | ||||
138 | /// If we can prove the backedge is untaken, remove it. This destroys the | |||
139 | /// loop, but leaves the (now trivially loop invariant) control flow and | |||
140 | /// side effects (if any) in place. | |||
141 | static LoopDeletionResult | |||
142 | breakBackedgeIfNotTaken(Loop *L, DominatorTree &DT, ScalarEvolution &SE, | |||
143 | LoopInfo &LI, MemorySSA *MSSA, | |||
144 | OptimizationRemarkEmitter &ORE) { | |||
145 | assert(L->isLCSSAForm(DT) && "Expected LCSSA!")((L->isLCSSAForm(DT) && "Expected LCSSA!") ? static_cast <void> (0) : __assert_fail ("L->isLCSSAForm(DT) && \"Expected LCSSA!\"" , "/build/llvm-toolchain-snapshot-12~++20210125100614+2cdb34efdac5/llvm/lib/Transforms/Scalar/LoopDeletion.cpp" , 145, __PRETTY_FUNCTION__)); | |||
146 | ||||
147 | if (!L->getLoopLatch()) | |||
148 | return LoopDeletionResult::Unmodified; | |||
149 | ||||
150 | auto *BTC = SE.getBackedgeTakenCount(L); | |||
151 | if (!BTC->isZero()) | |||
152 | return LoopDeletionResult::Unmodified; | |||
153 | ||||
154 | breakLoopBackedge(L, DT, SE, LI, MSSA); | |||
155 | return LoopDeletionResult::Deleted; | |||
156 | } | |||
157 | ||||
158 | /// Remove a loop if it is dead. | |||
159 | /// | |||
160 | /// A loop is considered dead either if it does not impact the observable | |||
161 | /// behavior of the program other than finite running time, or if it is | |||
162 | /// required to make progress by an attribute such as 'mustprogress' or | |||
163 | /// 'llvm.loop.mustprogress' and does not make any. This may remove | |||
164 | /// infinite loops that have been required to make progress. | |||
165 | /// | |||
166 | /// This entire process relies pretty heavily on LoopSimplify form and LCSSA in | |||
167 | /// order to make various safety checks work. | |||
168 | /// | |||
169 | /// \returns true if any changes were made. This may mutate the loop even if it | |||
170 | /// is unable to delete it due to hoisting trivially loop invariant | |||
171 | /// instructions out of the loop. | |||
172 | static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT, | |||
173 | ScalarEvolution &SE, LoopInfo &LI, | |||
174 | MemorySSA *MSSA, | |||
175 | OptimizationRemarkEmitter &ORE) { | |||
176 | assert(L->isLCSSAForm(DT) && "Expected LCSSA!")((L->isLCSSAForm(DT) && "Expected LCSSA!") ? static_cast <void> (0) : __assert_fail ("L->isLCSSAForm(DT) && \"Expected LCSSA!\"" , "/build/llvm-toolchain-snapshot-12~++20210125100614+2cdb34efdac5/llvm/lib/Transforms/Scalar/LoopDeletion.cpp" , 176, __PRETTY_FUNCTION__)); | |||
177 | ||||
178 | // We can only remove the loop if there is a preheader that we can branch from | |||
179 | // after removing it. Also, if LoopSimplify form is not available, stay out | |||
180 | // of trouble. | |||
181 | BasicBlock *Preheader = L->getLoopPreheader(); | |||
182 | if (!Preheader || !L->hasDedicatedExits()) { | |||
183 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Deletion requires Loop with preheader and dedicated exits.\n" ; } } while (false) | |||
184 | dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Deletion requires Loop with preheader and dedicated exits.\n" ; } } while (false) | |||
185 | << "Deletion requires Loop with preheader and dedicated exits.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Deletion requires Loop with preheader and dedicated exits.\n" ; } } while (false); | |||
186 | return LoopDeletionResult::Unmodified; | |||
187 | } | |||
188 | ||||
189 | BasicBlock *ExitBlock = L->getUniqueExitBlock(); | |||
190 | ||||
191 | if (ExitBlock && isLoopNeverExecuted(L)) { | |||
192 | LLVM_DEBUG(dbgs() << "Loop is proven to never execute, delete it!")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Loop is proven to never execute, delete it!" ; } } while (false); | |||
193 | // We need to forget the loop before setting the incoming values of the exit | |||
194 | // phis to undef, so we properly invalidate the SCEV expressions for those | |||
195 | // phis. | |||
196 | SE.forgetLoop(L); | |||
197 | // Set incoming value to undef for phi nodes in the exit block. | |||
198 | for (PHINode &P : ExitBlock->phis()) { | |||
199 | std::fill(P.incoming_values().begin(), P.incoming_values().end(), | |||
200 | UndefValue::get(P.getType())); | |||
201 | } | |||
202 | ORE.emit([&]() { | |||
203 | return OptimizationRemark(DEBUG_TYPE"loop-delete", "NeverExecutes", L->getStartLoc(), | |||
204 | L->getHeader()) | |||
205 | << "Loop deleted because it never executes"; | |||
206 | }); | |||
207 | deleteDeadLoop(L, &DT, &SE, &LI, MSSA); | |||
208 | ++NumDeleted; | |||
209 | return LoopDeletionResult::Deleted; | |||
210 | } | |||
211 | ||||
212 | // The remaining checks below are for a loop being dead because all statements | |||
213 | // in the loop are invariant. | |||
214 | SmallVector<BasicBlock *, 4> ExitingBlocks; | |||
215 | L->getExitingBlocks(ExitingBlocks); | |||
216 | ||||
217 | // We require that the loop has at most one exit block. Otherwise, we'd be in | |||
218 | // the situation of needing to be able to solve statically which exit block | |||
219 | // will be branched to, or trying to preserve the branching logic in a loop | |||
220 | // invariant manner. | |||
221 | if (!ExitBlock
| |||
222 | LLVM_DEBUG(dbgs() << "Deletion requires at most one exit block.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Deletion requires at most one exit block.\n" ; } } while (false); | |||
223 | return LoopDeletionResult::Unmodified; | |||
224 | } | |||
225 | // Finally, we have to check that the loop really is dead. | |||
226 | bool Changed = false; | |||
227 | if (!isLoopDead(L, SE, ExitingBlocks, ExitBlock, Changed, Preheader)) { | |||
228 | LLVM_DEBUG(dbgs() << "Loop is not invariant, cannot delete.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Loop is not invariant, cannot delete.\n" ; } } while (false); | |||
229 | return Changed ? LoopDeletionResult::Modified | |||
230 | : LoopDeletionResult::Unmodified; | |||
231 | } | |||
232 | ||||
233 | // Don't remove loops for which we can't solve the trip count unless the loop | |||
234 | // was required to make progress but has been determined to be dead. | |||
235 | const SCEV *S = SE.getConstantMaxBackedgeTakenCount(L); | |||
236 | if (isa<SCEVCouldNotCompute>(S) && | |||
237 | !L->getHeader()->getParent()->mustProgress() && !hasMustProgress(L)) { | |||
238 | LLVM_DEBUG(dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was " "not required to make progress.\n"; } } while (false) | |||
239 | "not required to make progress.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was " "not required to make progress.\n"; } } while (false); | |||
240 | return Changed ? LoopDeletionResult::Modified | |||
241 | : LoopDeletionResult::Unmodified; | |||
242 | } | |||
243 | ||||
244 | LLVM_DEBUG(dbgs() << "Loop is invariant, delete it!")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Loop is invariant, delete it!" ; } } while (false); | |||
245 | ORE.emit([&]() { | |||
246 | return OptimizationRemark(DEBUG_TYPE"loop-delete", "Invariant", L->getStartLoc(), | |||
247 | L->getHeader()) | |||
248 | << "Loop deleted because it is invariant"; | |||
249 | }); | |||
250 | deleteDeadLoop(L, &DT, &SE, &LI, MSSA); | |||
251 | ++NumDeleted; | |||
252 | ||||
253 | return LoopDeletionResult::Deleted; | |||
254 | } | |||
255 | ||||
256 | PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM, | |||
257 | LoopStandardAnalysisResults &AR, | |||
258 | LPMUpdater &Updater) { | |||
259 | ||||
260 | LLVM_DEBUG(dbgs() << "Analyzing Loop for deletion: ")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Analyzing Loop for deletion: " ; } } while (false); | |||
261 | LLVM_DEBUG(L.dump())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { L.dump(); } } while (false); | |||
262 | std::string LoopName = std::string(L.getName()); | |||
263 | // For the new PM, we can't use OptimizationRemarkEmitter as an analysis | |||
264 | // pass. Function analyses need to be preserved across loop transformations | |||
265 | // but ORE cannot be preserved (see comment before the pass definition). | |||
266 | OptimizationRemarkEmitter ORE(L.getHeader()->getParent()); | |||
267 | auto Result = deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, AR.MSSA, ORE); | |||
268 | ||||
269 | // If we can prove the backedge isn't taken, just break it and be done. This | |||
270 | // leaves the loop structure in place which means it can handle dispatching | |||
271 | // to the right exit based on whatever loop invariant structure remains. | |||
272 | if (Result != LoopDeletionResult::Deleted) | |||
273 | Result = merge(Result, breakBackedgeIfNotTaken(&L, AR.DT, AR.SE, AR.LI, | |||
274 | AR.MSSA, ORE)); | |||
275 | ||||
276 | if (Result == LoopDeletionResult::Unmodified) | |||
277 | return PreservedAnalyses::all(); | |||
278 | ||||
279 | if (Result == LoopDeletionResult::Deleted) | |||
280 | Updater.markLoopAsDeleted(L, LoopName); | |||
281 | ||||
282 | auto PA = getLoopPassPreservedAnalyses(); | |||
283 | if (AR.MSSA) | |||
284 | PA.preserve<MemorySSAAnalysis>(); | |||
285 | return PA; | |||
286 | } | |||
287 | ||||
288 | namespace { | |||
289 | class LoopDeletionLegacyPass : public LoopPass { | |||
290 | public: | |||
291 | static char ID; // Pass ID, replacement for typeid | |||
292 | LoopDeletionLegacyPass() : LoopPass(ID) { | |||
293 | initializeLoopDeletionLegacyPassPass(*PassRegistry::getPassRegistry()); | |||
294 | } | |||
295 | ||||
296 | // Possibly eliminate loop L if it is dead. | |||
297 | bool runOnLoop(Loop *L, LPPassManager &) override; | |||
298 | ||||
299 | void getAnalysisUsage(AnalysisUsage &AU) const override { | |||
300 | AU.addPreserved<MemorySSAWrapperPass>(); | |||
301 | getLoopAnalysisUsage(AU); | |||
302 | } | |||
303 | }; | |||
304 | } | |||
305 | ||||
306 | char LoopDeletionLegacyPass::ID = 0; | |||
307 | INITIALIZE_PASS_BEGIN(LoopDeletionLegacyPass, "loop-deletion",static void *initializeLoopDeletionLegacyPassPassOnce(PassRegistry &Registry) { | |||
308 | "Delete dead loops", false, false)static void *initializeLoopDeletionLegacyPassPassOnce(PassRegistry &Registry) { | |||
309 | INITIALIZE_PASS_DEPENDENCY(LoopPass)initializeLoopPassPass(Registry); | |||
310 | INITIALIZE_PASS_END(LoopDeletionLegacyPass, "loop-deletion",PassInfo *PI = new PassInfo( "Delete dead loops", "loop-deletion" , &LoopDeletionLegacyPass::ID, PassInfo::NormalCtor_t(callDefaultCtor <LoopDeletionLegacyPass>), false, false); Registry.registerPass (*PI, true); return PI; } static llvm::once_flag InitializeLoopDeletionLegacyPassPassFlag ; void llvm::initializeLoopDeletionLegacyPassPass(PassRegistry &Registry) { llvm::call_once(InitializeLoopDeletionLegacyPassPassFlag , initializeLoopDeletionLegacyPassPassOnce, std::ref(Registry )); } | |||
311 | "Delete dead loops", false, false)PassInfo *PI = new PassInfo( "Delete dead loops", "loop-deletion" , &LoopDeletionLegacyPass::ID, PassInfo::NormalCtor_t(callDefaultCtor <LoopDeletionLegacyPass>), false, false); Registry.registerPass (*PI, true); return PI; } static llvm::once_flag InitializeLoopDeletionLegacyPassPassFlag ; void llvm::initializeLoopDeletionLegacyPassPass(PassRegistry &Registry) { llvm::call_once(InitializeLoopDeletionLegacyPassPassFlag , initializeLoopDeletionLegacyPassPassOnce, std::ref(Registry )); } | |||
312 | ||||
313 | Pass *llvm::createLoopDeletionPass() { return new LoopDeletionLegacyPass(); } | |||
314 | ||||
315 | bool LoopDeletionLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) { | |||
316 | if (skipLoop(L)) | |||
| ||||
317 | return false; | |||
318 | DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | |||
319 | ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); | |||
320 | LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); | |||
321 | auto *MSSAAnalysis = getAnalysisIfAvailable<MemorySSAWrapperPass>(); | |||
322 | MemorySSA *MSSA = nullptr; | |||
323 | if (MSSAAnalysis
| |||
324 | MSSA = &MSSAAnalysis->getMSSA(); | |||
325 | // For the old PM, we can't use OptimizationRemarkEmitter as an analysis | |||
326 | // pass. Function analyses need to be preserved across loop transformations | |||
327 | // but ORE cannot be preserved (see comment before the pass definition). | |||
328 | OptimizationRemarkEmitter ORE(L->getHeader()->getParent()); | |||
329 | ||||
330 | LLVM_DEBUG(dbgs() << "Analyzing Loop for deletion: ")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { dbgs() << "Analyzing Loop for deletion: " ; } } while (false); | |||
331 | LLVM_DEBUG(L->dump())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("loop-delete")) { L->dump(); } } while (false); | |||
332 | ||||
333 | LoopDeletionResult Result = deleteLoopIfDead(L, DT, SE, LI, MSSA, ORE); | |||
334 | ||||
335 | // If we can prove the backedge isn't taken, just break it and be done. This | |||
336 | // leaves the loop structure in place which means it can handle dispatching | |||
337 | // to the right exit based on whatever loop invariant structure remains. | |||
338 | if (Result != LoopDeletionResult::Deleted) | |||
339 | Result = merge(Result, breakBackedgeIfNotTaken(L, DT, SE, LI, MSSA, ORE)); | |||
340 | ||||
341 | if (Result == LoopDeletionResult::Deleted) | |||
342 | LPM.markLoopAsDeleted(*L); | |||
343 | ||||
344 | return Result != LoopDeletionResult::Unmodified; | |||
345 | } |