Skip to content

Commit 4aca5ab

Browse files
Merge pull request #2972 from ElektroKill/fix/less-return-block-duplication
2 parents e8d9da1 + 8d7f8cb commit 4aca5ab

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23

34
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
45
{
@@ -566,5 +567,19 @@ public void SwitchInTryInLoopContinue()
566567
}
567568
}
568569
}
570+
571+
private static string ShouldNotDuplicateReturnStatementIntoTry(IDictionary<int, string> dict)
572+
{
573+
string value;
574+
lock (dict)
575+
{
576+
if (!dict.TryGetValue(1, out value))
577+
{
578+
value = "test";
579+
dict.Add(1, value);
580+
}
581+
}
582+
return value;
583+
}
569584
}
570585
}

ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2014 Daniel Grunwald
1+
// Copyright (c) 2014 Daniel Grunwald
22
//
33
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
44
// software and associated documentation files (the "Software"), to deal in the Software
@@ -137,7 +137,7 @@ void InlineVariableInReturnBlock(Block block, ILTransformContext context)
137137

138138
void SimplifyBranchChains(ILFunction function, ILTransformContext context)
139139
{
140-
List<(BlockContainer, Block)> blocksToAdd = new List<(BlockContainer, Block)>();
140+
List<(Block Block, BlockContainer TargetContainer)> blocksToMove = new List<(Block, BlockContainer)>();
141141
HashSet<Block> visitedBlocks = new HashSet<Block>();
142142
foreach (var branch in function.Descendants.OfType<Branch>())
143143
{
@@ -167,19 +167,17 @@ void SimplifyBranchChains(ILFunction function, ILTransformContext context)
167167
context.Step("Replace branch to return with return", branch);
168168
branch.ReplaceWith(targetBlock.Instructions[0].Clone());
169169
}
170-
else if (branch.TargetContainer != branch.Ancestors.OfType<BlockContainer>().First())
170+
else if (branch.TargetContainer != branch.Ancestors.OfType<BlockContainer>().First() && targetBlock.IncomingEdgeCount == 1)
171171
{
172172
// We don't want to always inline the return directly, because this
173173
// might force us to place the return within a loop, when it's better
174174
// placed outside.
175175
// But we do want to move the return block into the correct try-finally scope,
176176
// so that loop detection at least has the option to put it inside
177177
// the loop body.
178-
context.Step("Copy return block into try block", branch);
179-
Block blockCopy = (Block)branch.TargetBlock.Clone();
178+
context.Step("Move return block into try block", branch);
180179
BlockContainer localContainer = branch.Ancestors.OfType<BlockContainer>().First();
181-
blocksToAdd.Add((localContainer, blockCopy));
182-
branch.TargetBlock = blockCopy;
180+
blocksToMove.Add((targetBlock, localContainer));
183181
}
184182
}
185183
else if (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0] is Leave leave && leave.Value.MatchNop())
@@ -194,9 +192,10 @@ void SimplifyBranchChains(ILFunction function, ILTransformContext context)
194192
if (targetBlock.IncomingEdgeCount == 0)
195193
targetBlock.Instructions.Clear(); // mark the block for deletion
196194
}
197-
foreach (var (container, block) in blocksToAdd)
195+
foreach ((Block block, BlockContainer targetContainer) in blocksToMove)
198196
{
199-
container.Blocks.Add(block);
197+
block.Remove();
198+
targetContainer.Blocks.Add(block);
200199
}
201200
}
202201

0 commit comments

Comments
 (0)