Skip to content

Commit

Permalink
use INC DEC (#1286)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hecate2 authored Jan 24, 2025
1 parent 83e6095 commit 1e46dcf
Show file tree
Hide file tree
Showing 31 changed files with 291 additions and 195 deletions.
1 change: 1 addition & 0 deletions src/Neo.Compiler.CSharp/Optimizer/Strategies/Optimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public static (NefFile, ContractManifest, JObject?) Optimize(NefFile nef, Contra
(nef, manifest, debugInfo) = JumpCompresser.FoldJump(nef, manifest, debugInfo);
(nef, manifest, debugInfo) = Reachability.RemoveUncoveredInstructions(nef, manifest, debugInfo);
(nef, manifest, debugInfo) = Peephole.RemoveDupDrop(nef, manifest, debugInfo);
(nef, manifest, debugInfo) = Peephole.UseIncDec(nef, manifest, debugInfo);
(nef, manifest, debugInfo) = Peephole.FoldNotInEqual(nef, manifest, debugInfo);
(nef, manifest, debugInfo) = Peephole.UseNz(nef, manifest, debugInfo);
(nef, manifest, debugInfo) = Peephole.UseIsNull(nef, manifest, debugInfo);
Expand Down
118 changes: 118 additions & 0 deletions src/Neo.Compiler.CSharp/Optimizer/Strategies/Peephole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,124 @@ public static (NefFile, ContractManifest, JObject?) RemoveDupDrop(NefFile nef, C
oldAddressToInstruction);
}

/// <summary>
/// PUSH1 ADD -> INC
/// PUSH1 SUB -> DEC
/// PUSH2 ADD -> INC INC
/// PUSH2 SUB -> DEC DEC
/// </summary>
/// <param name="nef">Nef file</param>
/// <param name="manifest">Manifest</param>
/// <param name="debugInfo">Debug information</param>
/// <returns></returns>
[Strategy(Priority = 1 << 9)]
public static (NefFile, ContractManifest, JObject?) UseIncDec(NefFile nef, ContractManifest manifest, JObject? debugInfo = null)
{
ContractInBasicBlocks contractInBasicBlocks = new(nef, manifest, debugInfo);
List<(int a, Instruction i)> oldAddressAndInstructionsList = contractInBasicBlocks.coverage.addressAndInstructions;
Dictionary<int, Instruction> oldAddressToInstruction = contractInBasicBlocks.coverage.addressToInstructions;
(Dictionary<Instruction, Instruction> jumpSourceToTargets,
Dictionary<Instruction, (Instruction, Instruction)> trySourceToTargets,
Dictionary<Instruction, HashSet<Instruction>> jumpTargetToSources) =
(contractInBasicBlocks.coverage.jumpInstructionSourceToTargets,
contractInBasicBlocks.coverage.tryInstructionSourceToTargets,
contractInBasicBlocks.coverage.jumpTargetToSources);
Dictionary<int, int> oldSequencePointAddressToNew = new();
System.Collections.Specialized.OrderedDictionary simplifiedInstructionsToAddress = new();
int currentAddress = 0;
foreach ((int oldStartAddr, List<Instruction> basicBlock) in contractInBasicBlocks.sortedListInstructions)
{
int oldAddr = oldStartAddr;
for (int index = 0; index < basicBlock.Count; index++)
{
if (index + 1 < basicBlock.Count)
{
Instruction current = basicBlock[index];
Instruction next = basicBlock[index + 1];
if (OpCodeTypes.pushInt.Contains(current.OpCode)
&& new System.Numerics.BigInteger(current.Operand.Span) == 1
|| current.OpCode == OpCode.PUSH1)
{
if (next.OpCode == OpCode.ADD)
{
Script script = new Script(new byte[] { (byte)OpCode.INC });
Instruction inc = script.GetInstruction(0);
simplifiedInstructionsToAddress.Add(inc, currentAddress);
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
oldAddr += current.Size;
currentAddress += inc.Size;
oldAddr += next.Size;
index += 1;
OptimizedScriptBuilder.RetargetJump(current, inc,
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
continue;
}
if (next.OpCode == OpCode.SUB)
{
Script script = new Script(new byte[] { (byte)OpCode.DEC });
Instruction dec = script.GetInstruction(0);
simplifiedInstructionsToAddress.Add(dec, currentAddress);
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
oldAddr += current.Size;
currentAddress += dec.Size;
oldAddr += next.Size;
index += 1;
OptimizedScriptBuilder.RetargetJump(current, dec,
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
continue;
}
}
if (OpCodeTypes.pushInt.Contains(current.OpCode)
&& new System.Numerics.BigInteger(current.Operand.Span) == 2
|| current.OpCode == OpCode.PUSH2)
{
if (next.OpCode == OpCode.ADD)
{
Script script = new Script(new byte[] { (byte)OpCode.INC, (byte)OpCode.INC });
Instruction inc = script.GetInstruction(0);
simplifiedInstructionsToAddress.Add(inc, currentAddress);
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
oldAddr += current.Size;
currentAddress += inc.Size;
simplifiedInstructionsToAddress.Add(script.GetInstruction(inc.Size), currentAddress);
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
oldAddr += next.Size;
currentAddress += inc.Size;
index += 1;
OptimizedScriptBuilder.RetargetJump(current, inc,
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
continue;
}
if (next.OpCode == OpCode.SUB)
{
Script script = new Script(new byte[] { (byte)OpCode.DEC, (byte)OpCode.DEC });
Instruction dec = script.GetInstruction(0);
simplifiedInstructionsToAddress.Add(dec, currentAddress);
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
oldAddr += current.Size;
currentAddress += dec.Size;
simplifiedInstructionsToAddress.Add(script.GetInstruction(dec.Size), currentAddress);
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
oldAddr += next.Size;
currentAddress += dec.Size;
index += 1;
OptimizedScriptBuilder.RetargetJump(current, dec,
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
continue;
}
}
}
simplifiedInstructionsToAddress.Add(basicBlock[index], currentAddress);
currentAddress += basicBlock[index].Size;
oldAddr += basicBlock[index].Size;
}
}
return AssetBuilder.BuildOptimizedAssets(nef, manifest, debugInfo,
simplifiedInstructionsToAddress,
jumpSourceToTargets, trySourceToTargets,
oldAddressToInstruction, oldSequencePointAddressToNew: oldSequencePointAddressToNew);
}

/// <summary>
/// PUSH0 NUMEQUAL -> NZ NOT
/// PUSH0 NUMNOTEQUAL -> NZ
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace Neo.Compiler.CSharp.TestContracts
{
[Contract("0e26a6a9b6f37a54d5666aaa2efb71dc75abfdfa")]
[Contract("0xb6ae1662a8228ed73e372b0d0ea11716445a4281")]
public class Contract_Call
{
#pragma warning disable CS0626 // Method, operator, or accessor is marked external and has no attributes on it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public abstract class Contract1(Neo.SmartContract.Testing.SmartContractInitializ
/// <summary>
/// Optimization: "All"
/// </summary>
public static Neo.SmartContract.NefFile Nef => Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNXAQAMBAECAwTbMHBoQFcBAAwEAQIDBNswcEBXAQEMBAECAwPbMHB4SmgTUdBFaEBXAAF4QFcAAngSnkoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ+AeEBXAAJ4Ep5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfgHh5nkoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9A94cdyg==").AsSerializable<Neo.SmartContract.NefFile>();
public static Neo.SmartContract.NefFile Nef => Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNXAQAMBAECAwTbMHBoQFcBAAwEAQIDBNswcEBXAQEMBAECAwPbMHB4SmgTUdBFaEBXAAF4QFcAAnicnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ+AeEBXAAJ4nJxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfgHh5nkoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9A164YTw==").AsSerializable<Neo.SmartContract.NefFile>();

#endregion

Expand Down Expand Up @@ -60,11 +60,11 @@ public abstract class Contract1(Neo.SmartContract.Testing.SmartContractInitializ
/// Unsafe method
/// </summary>
/// <remarks>
/// Script: VwACeBKeSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4QA==
/// Script: VwACeJycSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4QA==
/// INITSLOT 0002 [64 datoshi]
/// LDARG0 [2 datoshi]
/// PUSH2 [1 datoshi]
/// ADD [8 datoshi]
/// INC [4 datoshi]
/// INC [4 datoshi]
/// DUP [2 datoshi]
/// PUSHINT32 00000080 [1 datoshi]
/// JMPGE 04 [2 datoshi]
Expand All @@ -90,11 +90,11 @@ public abstract class Contract1(Neo.SmartContract.Testing.SmartContractInitializ
/// Unsafe method
/// </summary>
/// <remarks>
/// Script: VwACeBKeSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4eZ5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfQA==
/// Script: VwACeJycSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4eZ5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfQA==
/// INITSLOT 0002 [64 datoshi]
/// LDARG0 [2 datoshi]
/// PUSH2 [1 datoshi]
/// ADD [8 datoshi]
/// INC [4 datoshi]
/// INC [4 datoshi]
/// DUP [2 datoshi]
/// PUSHINT32 00000080 [1 datoshi]
/// JMPGE 04 [2 datoshi]
Expand Down
Loading

0 comments on commit 1e46dcf

Please sign in to comment.