@@ -98,7 +98,7 @@ private BoissinotDestructor(ControlFlowGraph cfg) {
9898
9999 coalescePhis ();
100100 coalesceCopies ();
101-
101+
102102 remapLocals ();
103103 applyRemapping ();
104104
@@ -353,9 +353,36 @@ private void coalesceCopies() {
353353 if (!copy .isSynthetic () && copy .getExpression () instanceof VarExpr ) {
354354 Local lhs = copy .getVariable ().getLocal ();
355355 Local rhs = ((VarExpr ) copy .getExpression ()).getLocal ();
356- if (!isReservedRegister ((VersionedLocal ) rhs )) {
356+
357+ /*
358+ * Fix 4th December 2023
359+ * right and left must be both of same type to coalesce, or else
360+ * variables initialized with null and overriden in one branch
361+ * will have that one branch value propagated to the other branch
362+ *
363+ * eg:
364+ * var = nullconst
365+ * for (i in [0, 10)) {
366+ * if (cond) {
367+ * var = i
368+ * }
369+ * }
370+ * print(var)
371+ *
372+ * would become:
373+ *
374+ * var = nullconst
375+ * for (i in [0, 10)) {
376+ * var = i;
377+ * if (cond) {
378+ * }
379+ * }
380+ * print(var)
381+ *
382+ */
383+ if (!isReservedRegister ((VersionedLocal ) rhs ) && lhs .isStack () == rhs .isStack ()) {
357384 if (tryCoalesceCopyValue (lhs , rhs )) {
358- // System.out.println("COPYKILL(1) " + lhs + " == " + rhs);
385+ // System.out.println("COPYKILL(1) " + lhs + " == " + rhs);
359386 it .remove ();
360387 }
361388
@@ -398,32 +425,32 @@ private boolean isReservedRegister(VersionedLocal l) {
398425
399426 // Process the copy a = b. Returns true if a and b can be coalesced via value.
400427 private boolean tryCoalesceCopyValue (Local a , Local b ) {
401- // System.out.println("Enter COPY");
428+ //System.out.println("Enter COPY");
402429 CongruenceClass conClassA = getCongruenceClass (a );
403430 CongruenceClass conClassB = getCongruenceClass (b );
404431
405- // System.out.println(" A: " + conClassA);
406- // System.out.println(" B: " + conClassB);
432+ //System.out.println(" A: " + conClassA);
433+ //System.out.println(" B: " + conClassB);
407434
408- // System.out.println(" same=" + (conClassA == conClassB));
435+ //System.out.println(" same=" + (conClassA == conClassB));
409436 if (conClassA == conClassB )
410437 return true ;
411438
412439 if (conClassA .size () == 1 && conClassB .size () == 1 ) {
413440 boolean r = checkInterfereSingle (conClassA , conClassB );
414- // System.out.println(" single=" + r);
441+ //System.out.println(" single=" + r);
415442 return r ;
416443 }
417444
418445 boolean r2 = checkInterfere (conClassA , conClassB );
419- // System.out.println(" both=" + r2);
446+ //System.out.println(" both=" + r2);
420447 if (r2 ) {
421448 return false ;
422449 }
423450
424451 // merge congruence classes
425452 merge (conClassA , conClassB );
426- // System.out.println("Exit COPY");
453+ //System.out.println("Exit COPY");
427454 return true ;
428455 }
429456
@@ -570,21 +597,49 @@ private boolean dominates(Local a, Local b) {
570597 }
571598 }
572599
600+ /**
601+ * Purpose: The checkInterfere method determines if there is any interference
602+ * between two congruence classes, red and blue, in the context of SSA variable
603+ * coalescence.
604+ * <br/>
605+ * Process:
606+ * The method uses dominator tree traversal to compare elements from each class.
607+ * It maintains two stacks: one for the elements (dom) and one for their corresponding class (domClasses).
608+ * The method iterates through each class, comparing elements based on their dominance relationship.
609+ * If any pair of elements from different classes interfere, the method returns true.
610+ * Return Value: Returns true if there is interference between the two classes, otherwise false.
611+ *
612+ * Note: This method assumes that the CongruenceClass type and related methods like dominates, interference, and checkPreDomOrder are correctly implemented and available in the context.
613+ * @param red The first congruence class to check for interference.
614+ * @param blue The second congruence class to check for interference.
615+ * @return Returns true if there is interference between the two classes, otherwise false.
616+ */
573617 private boolean checkInterfere (CongruenceClass red , CongruenceClass blue ) {
574- // System.out.println("Enter interfere: " + red + " vs " + blue);
575- Stack <Local > dom = new Stack <>(); // dominator tree traversal stack
576- Stack <Integer > domClasses = new Stack <>(); // 0=red, 1=blue
577- int nr = 0 , nb = 0 ; // from the paper
578- Local ir = red .first (), ib = blue .first (); // iteration pointers
579- Local lr = red .last (), lb = blue .last (); // end sentinels
618+ // Initialize stacks for dominator tree traversal and class tracking
619+ Stack <Local > dom = new Stack <>();
620+ Stack <Integer > domClasses = new Stack <>();
621+
622+ // Initialize counters for red and blue classes
623+ int nr = 0 , nb = 0 ;
624+
625+ // Initialize iteration pointers and end sentinels for both classes
626+ Local ir = red .first (), ib = blue .first ();
627+ Local lr = red .last (), lb = blue .last ();
628+
629+ // Flags to track if there are more elements in each class
580630 boolean redHasNext = true , blueHasNext = true ;
581- equalAncOut .put (ir , null ); // these have no parents so we have to manually init them
631+
632+ // Manually initialize for elements with no parents
633+ equalAncOut .put (ir , null );
582634 equalAncOut .put (ib , null );
635+
583636 do {
584637 // System.out.println("\n ir, ib, lr, lb: " + ir + " " + ib + " " + lr + " " + lb);
585638 // System.out.println(" dom: " + dom);
586639 Local current ;
587640 int currentClass ;
641+
642+ // Determine which class to process next based on pre-dominator order
588643 if (!blueHasNext || (redHasNext && checkPreDomOrder (ir , ib ))) {
589644 // current = red[ir++] (Red case)
590645 current = ir ;
@@ -601,6 +656,7 @@ private boolean checkInterfere(CongruenceClass red, CongruenceClass blue) {
601656 ib = blue .higher (ib );
602657 }
603658
659+ // Pop elements from stack that do not dominate the current element
604660 while (!dom .isEmpty () && !dominates (dom .peek (), current )) {
605661 if (domClasses .peek () == 0 )
606662 nr --;
@@ -611,13 +667,20 @@ else if (domClasses.peek() == 1)
611667 dom .pop ();
612668 domClasses .pop ();
613669 }
670+
671+ // Check for interference
614672 if (!dom .isEmpty () && interference (current , dom .peek (), currentClass == domClasses .peek ())) {
615673 return true ;
616674 }
675+
676+ // Push current element and its class onto the stacks
617677 dom .push (current );
618678 domClasses .push (currentClass );
619- } while ((redHasNext && nb > 0 ) || (blueHasNext && nr > 0 ) || (redHasNext && blueHasNext ));
679+ }
680+ // Continue while there are elements in either class and unprocessed dominators in the stack
681+ while ((redHasNext && nb > 0 ) || (blueHasNext && nr > 0 ) || (redHasNext && blueHasNext ));
620682
683+ // No interference detected
621684 return false ;
622685 }
623686
0 commit comments