Skip to content

Commit c84605a

Browse files
committed
Fix #3468: Try harder to avoid ref locals if UseRefLocalsForAccurateOrderOfEvaluation is not enabled.
CopyPropagation will replace `ref StructWithStringField reference = ref array[0];` with: ``` var x = array; var y = 0; ``` and then every use of `reference` is replaced with `x[y]`. This lets us avoid rough locals while preserving the semantics in every case except that we re-order when a NullReferenceException/IndexOutOfRangeException occurs.
1 parent 317b4e8 commit c84605a

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,15 @@ static void RunOnBlock(Block block, ILTransformContext context, HashSet<ILVariab
8787
block.Instructions[i] = copiedExpr;
8888
}
8989
}
90-
else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr, splitVariables))
90+
else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr, splitVariables, context.Settings))
9191
{
9292
DoPropagate(v, copiedExpr, block, ref i, context);
9393
}
9494
}
9595
}
9696
}
9797

98-
static bool CanPerformCopyPropagation(ILVariable target, ILInstruction value, HashSet<ILVariable> splitVariables)
98+
static bool CanPerformCopyPropagation(ILVariable target, ILInstruction value, HashSet<ILVariable> splitVariables, DecompilerSettings settings)
9999
{
100100
Debug.Assert(target.StackType == value.ResultType);
101101
if (target.Type.IsSmallIntegerType())
@@ -107,14 +107,15 @@ static bool CanPerformCopyPropagation(ILVariable target, ILInstruction value, Ha
107107
switch (value.OpCode)
108108
{
109109
case OpCode.LdLoca:
110-
// case OpCode.LdElema:
111-
// case OpCode.LdFlda:
112110
case OpCode.LdsFlda:
113111
// All address-loading instructions always return the same value for a given operand/argument combination,
114112
// so they can be safely copied.
115113
// ... except for LdElema and LdFlda, because those might throw an exception, and we don't want to
116114
// change the place where the exception is thrown.
117115
return true;
116+
case OpCode.LdElema:
117+
case OpCode.LdFlda:
118+
return !settings.UseRefLocalsForAccurateOrderOfEvaluation;
118119
case OpCode.LdLoc:
119120
var v = ((LdLoc)value).Variable;
120121
if (splitVariables != null && splitVariables.Contains(v))

0 commit comments

Comments
 (0)