Skip to content

Commit 1e46dcf

Browse files
authored
use INC DEC (#1286)
1 parent 83e6095 commit 1e46dcf

31 files changed

+291
-195
lines changed

src/Neo.Compiler.CSharp/Optimizer/Strategies/Optimizer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public static (NefFile, ContractManifest, JObject?) Optimize(NefFile nef, Contra
6666
(nef, manifest, debugInfo) = JumpCompresser.FoldJump(nef, manifest, debugInfo);
6767
(nef, manifest, debugInfo) = Reachability.RemoveUncoveredInstructions(nef, manifest, debugInfo);
6868
(nef, manifest, debugInfo) = Peephole.RemoveDupDrop(nef, manifest, debugInfo);
69+
(nef, manifest, debugInfo) = Peephole.UseIncDec(nef, manifest, debugInfo);
6970
(nef, manifest, debugInfo) = Peephole.FoldNotInEqual(nef, manifest, debugInfo);
7071
(nef, manifest, debugInfo) = Peephole.UseNz(nef, manifest, debugInfo);
7172
(nef, manifest, debugInfo) = Peephole.UseIsNull(nef, manifest, debugInfo);

src/Neo.Compiler.CSharp/Optimizer/Strategies/Peephole.cs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,124 @@ public static (NefFile, ContractManifest, JObject?) RemoveDupDrop(NefFile nef, C
9090
oldAddressToInstruction);
9191
}
9292

93+
/// <summary>
94+
/// PUSH1 ADD -> INC
95+
/// PUSH1 SUB -> DEC
96+
/// PUSH2 ADD -> INC INC
97+
/// PUSH2 SUB -> DEC DEC
98+
/// </summary>
99+
/// <param name="nef">Nef file</param>
100+
/// <param name="manifest">Manifest</param>
101+
/// <param name="debugInfo">Debug information</param>
102+
/// <returns></returns>
103+
[Strategy(Priority = 1 << 9)]
104+
public static (NefFile, ContractManifest, JObject?) UseIncDec(NefFile nef, ContractManifest manifest, JObject? debugInfo = null)
105+
{
106+
ContractInBasicBlocks contractInBasicBlocks = new(nef, manifest, debugInfo);
107+
List<(int a, Instruction i)> oldAddressAndInstructionsList = contractInBasicBlocks.coverage.addressAndInstructions;
108+
Dictionary<int, Instruction> oldAddressToInstruction = contractInBasicBlocks.coverage.addressToInstructions;
109+
(Dictionary<Instruction, Instruction> jumpSourceToTargets,
110+
Dictionary<Instruction, (Instruction, Instruction)> trySourceToTargets,
111+
Dictionary<Instruction, HashSet<Instruction>> jumpTargetToSources) =
112+
(contractInBasicBlocks.coverage.jumpInstructionSourceToTargets,
113+
contractInBasicBlocks.coverage.tryInstructionSourceToTargets,
114+
contractInBasicBlocks.coverage.jumpTargetToSources);
115+
Dictionary<int, int> oldSequencePointAddressToNew = new();
116+
System.Collections.Specialized.OrderedDictionary simplifiedInstructionsToAddress = new();
117+
int currentAddress = 0;
118+
foreach ((int oldStartAddr, List<Instruction> basicBlock) in contractInBasicBlocks.sortedListInstructions)
119+
{
120+
int oldAddr = oldStartAddr;
121+
for (int index = 0; index < basicBlock.Count; index++)
122+
{
123+
if (index + 1 < basicBlock.Count)
124+
{
125+
Instruction current = basicBlock[index];
126+
Instruction next = basicBlock[index + 1];
127+
if (OpCodeTypes.pushInt.Contains(current.OpCode)
128+
&& new System.Numerics.BigInteger(current.Operand.Span) == 1
129+
|| current.OpCode == OpCode.PUSH1)
130+
{
131+
if (next.OpCode == OpCode.ADD)
132+
{
133+
Script script = new Script(new byte[] { (byte)OpCode.INC });
134+
Instruction inc = script.GetInstruction(0);
135+
simplifiedInstructionsToAddress.Add(inc, currentAddress);
136+
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
137+
oldAddr += current.Size;
138+
currentAddress += inc.Size;
139+
oldAddr += next.Size;
140+
index += 1;
141+
OptimizedScriptBuilder.RetargetJump(current, inc,
142+
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
143+
continue;
144+
}
145+
if (next.OpCode == OpCode.SUB)
146+
{
147+
Script script = new Script(new byte[] { (byte)OpCode.DEC });
148+
Instruction dec = script.GetInstruction(0);
149+
simplifiedInstructionsToAddress.Add(dec, currentAddress);
150+
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
151+
oldAddr += current.Size;
152+
currentAddress += dec.Size;
153+
oldAddr += next.Size;
154+
index += 1;
155+
OptimizedScriptBuilder.RetargetJump(current, dec,
156+
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
157+
continue;
158+
}
159+
}
160+
if (OpCodeTypes.pushInt.Contains(current.OpCode)
161+
&& new System.Numerics.BigInteger(current.Operand.Span) == 2
162+
|| current.OpCode == OpCode.PUSH2)
163+
{
164+
if (next.OpCode == OpCode.ADD)
165+
{
166+
Script script = new Script(new byte[] { (byte)OpCode.INC, (byte)OpCode.INC });
167+
Instruction inc = script.GetInstruction(0);
168+
simplifiedInstructionsToAddress.Add(inc, currentAddress);
169+
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
170+
oldAddr += current.Size;
171+
currentAddress += inc.Size;
172+
simplifiedInstructionsToAddress.Add(script.GetInstruction(inc.Size), currentAddress);
173+
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
174+
oldAddr += next.Size;
175+
currentAddress += inc.Size;
176+
index += 1;
177+
OptimizedScriptBuilder.RetargetJump(current, inc,
178+
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
179+
continue;
180+
}
181+
if (next.OpCode == OpCode.SUB)
182+
{
183+
Script script = new Script(new byte[] { (byte)OpCode.DEC, (byte)OpCode.DEC });
184+
Instruction dec = script.GetInstruction(0);
185+
simplifiedInstructionsToAddress.Add(dec, currentAddress);
186+
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
187+
oldAddr += current.Size;
188+
currentAddress += dec.Size;
189+
simplifiedInstructionsToAddress.Add(script.GetInstruction(dec.Size), currentAddress);
190+
oldSequencePointAddressToNew.Add(oldAddr, currentAddress);
191+
oldAddr += next.Size;
192+
currentAddress += dec.Size;
193+
index += 1;
194+
OptimizedScriptBuilder.RetargetJump(current, dec,
195+
jumpSourceToTargets, trySourceToTargets, jumpTargetToSources);
196+
continue;
197+
}
198+
}
199+
}
200+
simplifiedInstructionsToAddress.Add(basicBlock[index], currentAddress);
201+
currentAddress += basicBlock[index].Size;
202+
oldAddr += basicBlock[index].Size;
203+
}
204+
}
205+
return AssetBuilder.BuildOptimizedAssets(nef, manifest, debugInfo,
206+
simplifiedInstructionsToAddress,
207+
jumpSourceToTargets, trySourceToTargets,
208+
oldAddressToInstruction, oldSequencePointAddressToNew: oldSequencePointAddressToNew);
209+
}
210+
93211
/// <summary>
94212
/// PUSH0 NUMEQUAL -> NZ NOT
95213
/// PUSH0 NUMNOTEQUAL -> NZ

tests/Neo.Compiler.CSharp.TestContracts/Contract_ContractCall.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace Neo.Compiler.CSharp.TestContracts
1515
{
16-
[Contract("0e26a6a9b6f37a54d5666aaa2efb71dc75abfdfa")]
16+
[Contract("0xb6ae1662a8228ed73e372b0d0ea11716445a4281")]
1717
public class Contract_Call
1818
{
1919
#pragma warning disable CS0626 // Method, operator, or accessor is marked external and has no attributes on it

tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract1.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public abstract class Contract1(Neo.SmartContract.Testing.SmartContractInitializ
1616
/// <summary>
1717
/// Optimization: "All"
1818
/// </summary>
19-
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>();
19+
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>();
2020

2121
#endregion
2222

@@ -60,11 +60,11 @@ public abstract class Contract1(Neo.SmartContract.Testing.SmartContractInitializ
6060
/// Unsafe method
6161
/// </summary>
6262
/// <remarks>
63-
/// Script: VwACeBKeSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4QA==
63+
/// Script: VwACeJycSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4QA==
6464
/// INITSLOT 0002 [64 datoshi]
6565
/// LDARG0 [2 datoshi]
66-
/// PUSH2 [1 datoshi]
67-
/// ADD [8 datoshi]
66+
/// INC [4 datoshi]
67+
/// INC [4 datoshi]
6868
/// DUP [2 datoshi]
6969
/// PUSHINT32 00000080 [1 datoshi]
7070
/// JMPGE 04 [2 datoshi]
@@ -90,11 +90,11 @@ public abstract class Contract1(Neo.SmartContract.Testing.SmartContractInitializ
9090
/// Unsafe method
9191
/// </summary>
9292
/// <remarks>
93-
/// Script: VwACeBKeSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4eZ5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfQA==
93+
/// Script: VwACeJycSgIAAACALgQiCkoC////fzIeA/////8AAAAAkUoC////fzIMAwAAAAABAAAAn4B4eZ5KAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfQA==
9494
/// INITSLOT 0002 [64 datoshi]
9595
/// LDARG0 [2 datoshi]
96-
/// PUSH2 [1 datoshi]
97-
/// ADD [8 datoshi]
96+
/// INC [4 datoshi]
97+
/// INC [4 datoshi]
9898
/// DUP [2 datoshi]
9999
/// PUSHINT32 00000080 [1 datoshi]
100100
/// JMPGE 04 [2 datoshi]

0 commit comments

Comments
 (0)