Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an AppendNoPush optimization #2057

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DMCompiler/Bytecode/DreamProcOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ public enum DreamProcOpcode : byte {
[OpcodeMetadata]
Abs = 0x83,
// Peephole optimization opcodes
//0x84
[OpcodeMetadata(-1, OpcodeArgType.Reference)]
AppendNoPush = 0x84,
[OpcodeMetadata(-1, OpcodeArgType.Reference)]
AssignNoPush = 0x85,
[OpcodeMetadata(1, OpcodeArgType.Reference, OpcodeArgType.String)]
Expand Down
24 changes: 24 additions & 0 deletions DMCompiler/Optimizer/PeepholeOptimizations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

namespace DMCompiler.Optimizer;

// Append [ref]
// Pop
// -> AppendNoPush [ref]
internal sealed class AppendNoPush : IPeepholeOptimization {
public ReadOnlySpan<DreamProcOpcode> GetOpcodes() {
return [
DreamProcOpcode.Append,
DreamProcOpcode.Pop
];
}

public void Apply(List<IAnnotatedBytecode> input, int index) {
if (index + 1 >= input.Count) {
throw new ArgumentOutOfRangeException(nameof(index), "Bytecode index is outside the bounds of the input list.");
}

AnnotatedBytecodeInstruction firstInstruction = (AnnotatedBytecodeInstruction)(input[index]);
AnnotatedBytecodeReference assignTarget = firstInstruction.GetArg<AnnotatedBytecodeReference>(0);

input.RemoveRange(index, 2);
input.Insert(index, new AnnotatedBytecodeInstruction(DreamProcOpcode.AppendNoPush, [assignTarget]));
}
}

// Assign [ref]
// Pop
// -> AssignNoPush [ref]
Expand Down
24 changes: 17 additions & 7 deletions OpenDreamRuntime/Procs/DMOpcodeHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,19 @@ private static void ThrowInvalidAddOperation(DreamValue first, DreamValue second
}

public static ProcStatus Append(DMProcState state) {
state.Push(AppendHelper(state));
return ProcStatus.Continue;
}

/// <summary>
/// Identical to <see cref="Append"/> except it never pushes the result to the stack
/// </summary>
public static ProcStatus AppendNoPush(DMProcState state) {
AppendHelper(state);
return ProcStatus.Continue;
}

private static DreamValue AppendHelper(DMProcState state) {
DreamReference reference = state.ReadReference();
DreamValue second = state.Pop();
DreamValue first = state.GetReferenceValue(reference, peek: true);
Expand All @@ -753,12 +766,10 @@ public static ProcStatus Append(DMProcState state) {
} else if (first.TryGetValueAsDreamObject(out var firstObj)) {
if (firstObj != null) {
state.PopReference(reference);
state.Push(firstObj.OperatorAppend(second));

return ProcStatus.Continue;
} else {
result = second;
return firstObj.OperatorAppend(second);
}

result = second;
} else if (!second.IsNull) {
switch (first.Type) {
case DreamValue.DreamValueType.Float when second.Type == DreamValue.DreamValueType.Float:
Expand All @@ -775,8 +786,7 @@ public static ProcStatus Append(DMProcState state) {
}

state.AssignReference(reference, result);
state.Push(result);
return ProcStatus.Continue;
return result;
}

public static ProcStatus Increment(DMProcState state) {
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/Procs/DMProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ public sealed class DMProcState : ProcState {
{DreamProcOpcode.Negate, DMOpcodeHandlers.Negate},
{DreamProcOpcode.Modulus, DMOpcodeHandlers.Modulus},
{DreamProcOpcode.Append, DMOpcodeHandlers.Append},
{DreamProcOpcode.AppendNoPush, DMOpcodeHandlers.AppendNoPush},
{DreamProcOpcode.CreateRangeEnumerator, DMOpcodeHandlers.CreateRangeEnumerator},
{DreamProcOpcode.Input, DMOpcodeHandlers.Input},
{DreamProcOpcode.CompareLessThanOrEqual, DMOpcodeHandlers.CompareLessThanOrEqual},
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/Procs/ProcDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public ITuple DecodeInstruction() {
case DreamProcOpcode.OutputReference:
case DreamProcOpcode.PushReferenceValue:
case DreamProcOpcode.PopReference:
case DreamProcOpcode.AppendNoPush:
case DreamProcOpcode.AssignNoPush:
case DreamProcOpcode.ReturnReferenceValue:
return (opcode, ReadReference());
Expand Down
Loading