@@ -419,52 +419,70 @@ func (po *poset) aliasnewnode(n1, n2 *Value) {
419419 po .upushalias (n2 .ID , 0 )
420420}
421421
422- // aliasnode records that n2 (already in the poset) is an alias of n1
423- func (po * poset ) aliasnode (n1 , n2 * Value ) {
422+ // aliasnodes records that all the nodes i2s are aliases of a single master node n1.
423+ // aliasnodes takes care of rearranging the DAG, changing references of parent/children
424+ // of nodes in i2s, so that they point to n1 instead.
425+ // Complexity is O(n) (with n being the total number of nodes in the poset, not just
426+ // the number of nodes being aliased).
427+ func (po * poset ) aliasnodes (n1 * Value , i2s bitset ) {
424428 i1 := po .values [n1 .ID ]
425429 if i1 == 0 {
426430 panic ("aliasnode for non-existing node" )
427431 }
428-
429- i2 := po .values [n2 .ID ]
430- if i2 == 0 {
431- panic ("aliasnode for non-existing node" )
432+ if i2s .Test (i1 ) {
433+ panic ("aliasnode i2s contains n1 node" )
432434 }
433- // Rename all references to i2 into i1
434- // (do not touch i1 itself, otherwise we can create useless self-loops)
435+
436+ // Go through all the nodes to adjust parent/chidlren of nodes in i2s
435437 for idx , n := range po .nodes {
436- if uint32 (idx ) != i1 {
437- l , r := n .l , n .r
438- if l .Target () == i2 {
439- po .setchl (uint32 (idx ), newedge (i1 , l .Strict ()))
440- po .upush (undoSetChl , uint32 (idx ), l )
438+ // Do not touch i1 itself, otherwise we can create useless self-loops
439+ if uint32 (idx ) == i1 {
440+ continue
441+ }
442+ l , r := n .l , n .r
443+
444+ // Rename all references to i2s into i1
445+ if i2s .Test (l .Target ()) {
446+ po .setchl (uint32 (idx ), newedge (i1 , l .Strict ()))
447+ po .upush (undoSetChl , uint32 (idx ), l )
448+ }
449+ if i2s .Test (r .Target ()) {
450+ po .setchr (uint32 (idx ), newedge (i1 , r .Strict ()))
451+ po .upush (undoSetChr , uint32 (idx ), r )
452+ }
453+
454+ // Connect all chidren of i2s to i1 (unless those children
455+ // are in i2s as well, in which case it would be useless)
456+ if i2s .Test (uint32 (idx )) {
457+ if l != 0 && ! i2s .Test (l .Target ()) {
458+ po .addchild (i1 , l .Target (), l .Strict ())
441459 }
442- if r .Target () == i2 {
443- po .setchr (uint32 (idx ), newedge (i1 , r .Strict ()))
444- po .upush (undoSetChr , uint32 (idx ), r )
460+ if r != 0 && ! i2s .Test (r .Target ()) {
461+ po .addchild (i1 , r .Target (), r .Strict ())
445462 }
463+ po .setchl (uint32 (idx ), 0 )
464+ po .setchr (uint32 (idx ), 0 )
465+ po .upush (undoSetChl , uint32 (idx ), l )
466+ po .upush (undoSetChr , uint32 (idx ), r )
446467 }
447468 }
448469
449470 // Reassign all existing IDs that point to i2 to i1.
450471 // This includes n2.ID.
451472 for k , v := range po .values {
452- if v == i2 {
473+ if i2s . Test ( v ) {
453474 po .values [k ] = i1
454- po .upushalias (k , i2 )
475+ po .upushalias (k , v )
455476 }
456477 }
457478
458- if n2 .isGenericIntConst () {
459- val := n2 .AuxInt
460- if po .flags & posetFlagUnsigned != 0 {
461- val = int64 (n2 .AuxUnsigned ())
462- }
463- if po .constants [val ] != i2 {
464- panic ("aliasing constant which is not registered" )
479+ // If one of the aliased nodes is a constant, then make sure
480+ // po.constants is updated to point to the master node.
481+ for val , idx := range po .constants {
482+ if i2s .Test (idx ) {
483+ po .constants [val ] = i1
484+ po .upushconst (i1 , idx )
465485 }
466- po .constants [val ] = i1
467- po .upushconst (i1 , i2 )
468486 }
469487}
470488
@@ -623,7 +641,9 @@ func (po *poset) collapsepath(n1, n2 *Value) bool {
623641 // TODO: for now, only handle the simple case of i2 being child of i1
624642 l , r := po .children (i1 )
625643 if l .Target () == i2 || r .Target () == i2 {
626- po .aliasnode (n1 , n2 )
644+ i2s := newBitset (int (po .lastidx ) + 1 )
645+ i2s .Set (i2 )
646+ po .aliasnodes (n1 , i2s )
627647 po .addchild (i1 , i2 , false )
628648 return true
629649 }
@@ -1135,11 +1155,9 @@ func (po *poset) SetEqual(n1, n2 *Value) bool {
11351155
11361156 // Set n2 as alias of n1. This will also update all the references
11371157 // to n2 to become references to n1
1138- po .aliasnode (n1 , n2 )
1139-
1140- // Connect i2 (now dummy) as child of i1. This allows to keep the correct
1141- // order with its children.
1142- po .addchild (i1 , i2 , false )
1158+ i2s := newBitset (int (po .lastidx ) + 1 )
1159+ i2s .Set (i2 )
1160+ po .aliasnodes (n1 , i2s )
11431161 }
11441162 return true
11451163}
0 commit comments