@@ -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
0 commit comments