Browse Source

LoopDetection: find appropriate exit points

pull/728/merge
Daniel Grunwald 9 years ago
parent
commit
66dee6c6f9
  1. 15
      ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs

15
ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs

@ -286,10 +286,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var child in node.DominatorTreeChildren) { foreach (var child in node.DominatorTreeChildren) {
codeAmount += PickExitPoint(child, ref exitPoint, ref exitPointCodeAmount); codeAmount += PickExitPoint(child, ref exitPoint, ref exitPointCodeAmount);
} }
if (codeAmount > exitPointCodeAmount && !context.ControlFlowGraph.HasReachableExit(node)) { if (codeAmount > exitPointCodeAmount
// dominanceFrontier(node) is empty && !context.ControlFlowGraph.HasReachableExit(node)
&& ((Block)node.UserData).Parent == currentBlockContainer)
{
// HasReachableExit(node) == false
// -> there are no nodes n so that `node` dominates a predecessor of n but not n itself // -> there are no nodes n so that `node` dominates a predecessor of n but not n itself
// -> there is no control flow out of `node` back into the loop, so it's usable as exit point // -> there is no control flow out of `node` back into the loop, so it's usable as exit point
// Additionally, we require that the block wasn't already moved into a nested loop,
// since there's no way to jump into the middle of that loop when we need to exit.
// NB: this is the only reason why we detect nested loops before outer loops:
// If we detected the outer loop first, the outer loop might pick an exit point
// that prevents us from finding a nice exit for the inner loops, causing
// unnecessary gotos.
exitPoint = node; exitPoint = node;
exitPointCodeAmount = codeAmount; exitPointCodeAmount = codeAmount;
} }
@ -391,7 +401,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// </summary> /// </summary>
void ConstructLoop(List<ControlFlowNode> loop, ControlFlowNode exitPoint) void ConstructLoop(List<ControlFlowNode> loop, ControlFlowNode exitPoint)
{ {
exitPoint = null; // TODO
Block oldEntryPoint = (Block)loop[0].UserData; Block oldEntryPoint = (Block)loop[0].UserData;
Block exitTargetBlock = (Block)exitPoint?.UserData; Block exitTargetBlock = (Block)exitPoint?.UserData;

Loading…
Cancel
Save