Browse Source

Optimize: Reduce and merge unnecessary move instructions

Akeit0 1 year ago
parent
commit
ddf6d44bb0

+ 78 - 0
src/Lua/CodeAnalysis/Compilation/FunctionCompilationContext.cs

@@ -110,6 +110,84 @@ public class FunctionCompilationContext : IDisposable
         instructionPositions.Add(position);
         instructionPositions.Add(position);
     }
     }
 
 
+    /// <summary>
+    /// Push or merge the new instruction.
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void PushOrMergeInstruction(in Instruction instruction, in SourcePosition position,ref bool incrementStackPosition)
+    {
+        if(instructions.Length==0)
+        {
+            instructions.Add(instruction);
+            instructionPositions.Add(position);
+            return;
+        }
+        ref var lastInstruction = ref instructions.AsSpan()[^1];
+        var opcode = instruction.OpCode;
+        switch (opcode)
+        {
+            case OpCode.Move:
+               if (lastInstruction.A ==instruction.B)
+               {
+                    switch (lastInstruction.OpCode)
+                    {
+                        case OpCode.GetTable:
+                        case OpCode.Add:
+                        case OpCode.Sub:
+                        case OpCode.Mul:
+                        case OpCode.Div:
+                        case OpCode.Mod:
+                        case OpCode.Pow:
+                        {
+                            lastInstruction.A = instruction.A;
+                            incrementStackPosition = false;
+                            return;
+                        }
+                    }
+               }
+               break;
+            case OpCode.GetTable:
+            {
+                if (lastInstruction.OpCode == OpCode.Move)
+                {
+                    var b = instruction.B;
+                    if (instruction.A==b&&lastInstruction.A == b)
+                    {
+                        lastInstruction=Instruction.GetTable(instruction.A, lastInstruction.B, instruction.C);
+                        incrementStackPosition = false;
+                        return;
+                    }
+                }
+                break;
+            }
+            case OpCode.SetTable:
+            {
+                if (lastInstruction.OpCode == OpCode.Move)
+                {
+                    var lastB = lastInstruction.B;
+                    var lastA = lastInstruction.A;
+                    if (lastB<255 && lastA == instruction.A)
+                    {
+                        lastInstruction=Instruction.SetTable((byte)(lastB), instruction.B, instruction.C);
+                        incrementStackPosition = false;
+                        return;
+                    }
+
+                    if (lastA == instruction.C)
+                    {
+                        lastInstruction=Instruction.SetTable(instruction.A, instruction.B, instruction.C);
+                        incrementStackPosition = false;
+                        return;
+                    }
+                }
+                break;
+            }
+        }
+        
+        instructions.Add(instruction);
+        instructionPositions.Add(position);
+    }
+    
     /// <summary>
     /// <summary>
     /// Gets the index of the constant from the value, or if the constant is not registered it is added and its index is returned.
     /// Gets the index of the constant from the value, or if the constant is not registered it is added and its index is returned.
     /// </summary>
     /// </summary>

+ 16 - 2
src/Lua/CodeAnalysis/Compilation/ScopeCompilationContext.cs

@@ -33,6 +33,8 @@ public class ScopeCompilationContext : IDisposable
     readonly Dictionary<ReadOnlyMemory<char>, LocalVariableDescription> localVariables = new(256, Utf16StringMemoryComparer.Default);
     readonly Dictionary<ReadOnlyMemory<char>, LocalVariableDescription> localVariables = new(256, Utf16StringMemoryComparer.Default);
     readonly Dictionary<ReadOnlyMemory<char>, LabelDescription> labels = new(32, Utf16StringMemoryComparer.Default);
     readonly Dictionary<ReadOnlyMemory<char>, LabelDescription> labels = new(32, Utf16StringMemoryComparer.Default);
 
 
+    byte lastLocalVariableIndex;
+    
     public byte StackStartPosition { get; private set; }
     public byte StackStartPosition { get; private set; }
     public byte StackPosition { get; set; }
     public byte StackPosition { get; set; }
 
 
@@ -72,8 +74,18 @@ public class ScopeCompilationContext : IDisposable
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public void PushInstruction(in Instruction instruction, SourcePosition position, bool incrementStackPosition = false)
     public void PushInstruction(in Instruction instruction, SourcePosition position, bool incrementStackPosition = false)
     {
     {
-        Function.PushInstruction(instruction, position);
-        if (incrementStackPosition) StackPosition++;
+        if (lastLocalVariableIndex == StackPosition - 1)
+        {
+            Function.PushInstruction(instruction, position);
+        }
+        else
+        {
+            Function.PushOrMergeInstruction(instruction, position, ref incrementStackPosition);
+        }
+        if(incrementStackPosition)
+        {
+            StackPosition++;
+        }
     }
     }
 
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -92,6 +104,7 @@ public class ScopeCompilationContext : IDisposable
     public void AddLocalVariable(ReadOnlyMemory<char> name, LocalVariableDescription description)
     public void AddLocalVariable(ReadOnlyMemory<char> name, LocalVariableDescription description)
     {
     {
         localVariables[name] = description;
         localVariables[name] = description;
+        lastLocalVariableIndex = description.RegisterIndex;
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -157,6 +170,7 @@ public class ScopeCompilationContext : IDisposable
         HasCapturedLocalVariables = false;
         HasCapturedLocalVariables = false;
         localVariables.Clear();
         localVariables.Clear();
         labels.Clear();
         labels.Clear();
+        lastLocalVariableIndex = 0;
     }
     }
 
 
     /// <summary>
     /// <summary>