|
|
|
@ -17,6 +17,7 @@
@@ -17,6 +17,7 @@
|
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
|
|
namespace ICSharpCode.Decompiler.IL |
|
|
|
|
{ |
|
|
|
@ -63,5 +64,44 @@ namespace ICSharpCode.Decompiler.IL
@@ -63,5 +64,44 @@ namespace ICSharpCode.Decompiler.IL
|
|
|
|
|
return (inst1 & readFlag) != 0 && (inst2 & writeFlag) != 0 |
|
|
|
|
|| (inst2 & readFlag) != 0 && (inst1 & writeFlag) != 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets whether the instruction sequence 'inst1; inst2;' may be ordered to 'inst2; inst1;'
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal static bool MayReorder(ILInstruction inst1, ILInstruction inst2) |
|
|
|
|
{ |
|
|
|
|
// If both instructions perform an impure action, we cannot reorder them
|
|
|
|
|
if (!IsPure(inst1.Flags) && !IsPure(inst2.Flags)) |
|
|
|
|
return false; |
|
|
|
|
// We cannot reorder if inst2 might write what inst1 looks at
|
|
|
|
|
if (Inst2MightWriteToVariableReadByInst1(inst1, inst2)) |
|
|
|
|
return false; |
|
|
|
|
// and the same in reverse:
|
|
|
|
|
if (Inst2MightWriteToVariableReadByInst1(inst2, inst1)) |
|
|
|
|
return false; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool Inst2MightWriteToVariableReadByInst1(ILInstruction inst1, ILInstruction inst2) |
|
|
|
|
{ |
|
|
|
|
if (!inst1.HasFlag(InstructionFlags.MayReadLocals)) { |
|
|
|
|
// quick exit if inst1 doesn't read any variables
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
var variables = inst1.Descendants.OfType<LdLoc>().Select(load => load.Variable).ToHashSet(); |
|
|
|
|
if (inst2.HasFlag(InstructionFlags.SideEffect) && variables.Any(v => v.AddressCount > 0)) { |
|
|
|
|
// If inst2 might have indirect writes, we cannot reorder with any loads of variables that have their address taken.
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
foreach (var inst in inst2.Descendants) { |
|
|
|
|
if (inst.HasDirectFlag(InstructionFlags.MayWriteLocals)) { |
|
|
|
|
ILVariable v = ((IInstructionWithVariableOperand)inst).Variable; |
|
|
|
|
if (variables.Contains(v)) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |