@@ -133,111 +133,73 @@ private void replaceInstruction(BasicBlock block, Instruction.ParallelCopyInstru
133133 block .replaceInstruction (pcopy , instructions );
134134 }
135135
136- static final class Copy {
137- Operand src ;
138- Operand dest ;
139- boolean removed = false ;
136+ private boolean isEqual (Operand op1 , Operand op2 ) {
137+ if (op1 instanceof Operand .RegisterOperand reg1 && op2 instanceof Operand .RegisterOperand reg2 )
138+ return reg1 .reg .id == reg2 .reg .id ;
139+ return false ;
140+ }
140141
141- public Copy (Operand src , Operand dest ) {
142- this .src = src ;
143- this .dest = dest ;
144- }
142+ // The parallel move algo below is from
143+ // https://xavierleroy.org/publi/parallel-move.pdf
144+ // Tilting at windmills with Coq:
145+ // formal verification of a compilation algorithm
146+ // for parallel moves
147+ // Laurence Rideau, Bernard Paul Serpette, Xavier Leroy
148+ enum MoveStatus {
149+ TO_MOVE , BEING_MOVED , MOVED
145150 }
146151
147- List <Copy > getCopies (Instruction .ParallelCopyInstruction pcopy ) {
148- List <Copy > copies = new ArrayList <>();
149- for (int i = 0 ; i < pcopy .sourceOperands .size (); i ++) {
150- var src = pcopy .sourceOperands .get (i );
151- var dest = pcopy .destOperands .get (i );
152- if (src instanceof Operand .RegisterOperand srcR && dest instanceof Operand .RegisterOperand destR ) {
153- if (srcR .reg .id == destR .reg .id )
154- continue ;
155- }
156- copies .add (new Copy (src ,dest ));
152+ static final class MoveCtx {
153+ Operand [] src ;
154+ Operand [] dst ;
155+ MoveStatus [] status ;
156+ ArrayList <Instruction > copyInstructions ;
157+
158+ MoveCtx (Instruction .ParallelCopyInstruction pcopy ) {
159+ src = pcopy .sourceOperands .toArray (new Operand [0 ]);
160+ dst = pcopy .destOperands .toArray (new Operand [0 ]);
161+ copyInstructions = new ArrayList <Instruction >();
162+ status = new MoveStatus [src .length ];
163+ Arrays .fill (status , MoveStatus .TO_MOVE );
157164 }
158- return copies ;
159165 }
160166
161- private void sequenceParallelCopy (BasicBlock block , Instruction .ParallelCopyInstruction pcopy ) {
162- var copyInstructions = new ArrayList <Instruction >();
163- var copies = getCopies (pcopy );
164-
165- while (copies .size () > 0 ) {
166- boolean progress = false ;
167-
168- for (var copy : copies ) {
169- boolean cycle = false ;
170- for (int i = 0 ; i < copies .size (); i ++) {
171- if (copy .removed == true )
172- continue ;
173- if (copy .src .equals (copies .get (i ).dest )) {
174- cycle = true ;
175- break ;
167+ private void moveOne (MoveCtx ctx , int i ) {
168+ Operand [] src = ctx .src ;
169+ Operand [] dst = ctx .dst ;
170+ if (!isEqual (src [i ], dst [i ])) {
171+ ctx .status [i ] = MoveStatus .BEING_MOVED ;
172+ for (int j = 0 ; j < src .length ; j ++) {
173+ if (isEqual (src [j ],dst [i ])) {
174+ // cycle found
175+ switch (ctx .status [j ]) {
176+ case TO_MOVE :
177+ moveOne (ctx , j );
178+ break ;
179+ case BEING_MOVED :
180+ var temp = new Operand .RegisterOperand (function .registerPool .newTempReg (src [j ].type ));
181+ ctx .copyInstructions .add (new Instruction .Move (src [j ], temp ));
182+ src [j ] = temp ;
183+ break ;
184+ case MOVED :
185+ break ;
176186 }
177187 }
178- if (!cycle ) {
179- copyInstructions .add (new Instruction .Move (copy .src ,copy .dest ));
180- copy .removed = true ;
181- progress = true ;
182- }
183188 }
184-
185- copies .removeIf (c ->c .removed );
186- if (progress )
187- continue ;
188-
189- var copy = copies .removeFirst ();
190- var temp = new Operand .RegisterOperand (function .registerPool .newTempReg (copy .src .type ));
191- copyInstructions .add (new Instruction .Move (copy .src ,temp ));
192- copies .add (new Copy (copy .dest ,temp ));
189+ ctx .copyInstructions .add (new Instruction .Move (src [i ], dst [i ]));
190+ ctx .status [i ] = MoveStatus .MOVED ;
193191 }
194- replaceInstruction (block ,pcopy ,copyInstructions );
195192 }
196193
197- private void sequenceParallelCopyX (BasicBlock block , Instruction .ParallelCopyInstruction pcopy ) {
198- var copyInstructions = new ArrayList <Instruction >();
199- var ready = new ArrayList <Operand >();
200- var toDo = new ArrayList <Operand >();
201- var directPred = new HashMap <Operand ,Operand >();
202- var loc = new HashMap <Operand ,Operand >();
203- for (int i = 0 ; i <pcopy .sourceOperands .size (); i ++) {
204- var a = pcopy .sourceOperands .get (i );
205- var b = pcopy .destOperands .get (i );
206- if (a .equals (b ))
207- continue ;
208- loc .put (a ,a );
209- directPred .put (b ,a );
210- toDo .add (b );
211- }
212- for (int i = 0 ; i <pcopy .sourceOperands .size (); i ++) {
213- var a = pcopy .sourceOperands .get (i );
214- var b = pcopy .destOperands .get (i );
215- if (a == b )
216- continue ;
217- if (loc .get (b ) == null )
218- ready .add (b );
219- }
220- while (!toDo .isEmpty ()) {
221- while (!ready .isEmpty ()) {
222- var b = ready .removeLast ();
223- var a = directPred .get (b );
224- var c = loc .get (a );
225- copyInstructions .add (new Instruction .Move (c ,b ));
226- loc .put (a ,b );
227- if (a == c && directPred .get (a ) != null )
228- ready .add (a );
229- }
230- var b = toDo .removeLast ();
231- if (b == loc .get (directPred .get (b ))) {
232- var n = new Operand .RegisterOperand (function .registerPool .newTempReg (b .type ));
233- copyInstructions .add (new Instruction .Move (b ,n ));
234- loc .put (b ,n );
235- ready .add (b );
236- }
237- }
238- replaceInstruction (block ,pcopy ,copyInstructions );
194+ private void sequenceParallelCopy (BasicBlock block , Instruction .ParallelCopyInstruction parallelCopyInstruction ) {
195+ var ctx = new MoveCtx (parallelCopyInstruction );
196+ for (int i = 0 ; i < ctx .src .length ; i ++)
197+ if (ctx .status [i ] == MoveStatus .TO_MOVE )
198+ moveOne (ctx ,i );
199+ replaceInstruction (block ,parallelCopyInstruction ,ctx .copyInstructions );
239200 }
240201
202+
241203 static final class PCopy {
242204 BasicBlock block ;
243205 /**
0 commit comments