@@ -296,7 +296,7 @@ def find
296296 end
297297
298298 def make_equal_to ( other )
299- @forwarded = other
299+ find . instance_variable_set ( : @forwarded, other . find )
300300 end
301301
302302 # Override in subclasses
@@ -545,7 +545,7 @@ def initialize(fun)
545545 @preds = Hash . new { |h , k | h [ k ] = [ ] }
546546 @blocks . each do |block |
547547 block . insns . each do |insn |
548- insn = fun . find ( insn )
548+ insn = insn . find
549549 case insn
550550 when Jump then @preds [ insn . target . target . id ] << block
551551 when IfTrue then @preds [ insn . target . target . id ] << block
@@ -655,30 +655,14 @@ def new_insn(insn)
655655 insn
656656 end
657657
658- # ─── Union-Find (delegates to per-instruction forwarding) ──────
659- # Each Insn carries its own @forwarded pointer. These are convenience
660- # methods on Function that delegate to insn.find / insn.make_equal_to.
661-
662- def make_equal_to ( old_insn , new_insn )
663- old_insn . find . make_equal_to ( new_insn )
664- end
665-
666- def find ( insn ) = insn . find
667-
668- # Type of the canonical representative
669- def type_of ( insn ) = insn . find . type
670-
671- # Check if insn's type is a subtype of target_type
672- def is_a? ( insn , target_type ) = insn . find . type <= target_type
673-
674658 # Infer the type of a newly created instruction
675659 def infer_type ( insn )
676660 case insn
677661 when Const
678662 insn . type # already set at creation
679663 when FixnumAdd , FixnumSub , FixnumMult
680- lt = type_of ( insn . left )
681- rt = type_of ( insn . right )
664+ lt = insn . left . find . type
665+ rt = insn . right . find . type
682666 if lt . has_const? && rt . has_const? && lt . fixnum? && rt . fixnum?
683667 result = case insn
684668 when FixnumAdd then lt . const_val + rt . const_val
@@ -690,7 +674,7 @@ def infer_type(insn)
690674 Types ::Fixnum
691675 end
692676 when FixnumLt , FixnumEq , FixnumGt then Types ::CBool
693- when GuardType then type_of ( insn . val ) & insn . guard_type
677+ when GuardType then insn . val . find . type & insn . guard_type
694678 when Test then Types ::CBool
695679 else insn . type
696680 end
@@ -1070,22 +1054,22 @@ def type_specialize
10701054 old_insns = block . insns . dup
10711055 block . insns . clear
10721056 old_insns . each do |insn |
1073- insn = find ( insn )
1057+ insn = insn . find
10741058 next push_insn_id ( block , insn ) unless insn . is_a? ( Send )
10751059 next push_insn_id ( block , insn ) unless FIXNUM_SEND_MAP . key? ( insn . method_name )
10761060
1077- recv_type = type_of ( insn . recv )
1078- arg_type = insn . args [ 0 ] ? type_of ( insn . args [ 0 ] ) : nil
1061+ recv_type = insn . recv . find . type
1062+ arg_type = insn . args [ 0 ] ? insn . args [ 0 ] . find . type : nil
10791063
10801064 unless recv_type . fixnum? && arg_type &.fixnum?
10811065 push_insn_id ( block , insn ) ; next
10821066 end
10831067
10841068 # Guard both operands
1085- gl = push_insn ( block , GuardType . new ( find ( insn . recv ) , Types ::Fixnum , insn . state ) )
1086- gl . type = type_of ( insn . recv ) & Types ::Fixnum
1087- gr = push_insn ( block , GuardType . new ( find ( insn . args [ 0 ] ) , Types ::Fixnum , insn . state ) )
1088- gr . type = type_of ( insn . args [ 0 ] ) & Types ::Fixnum
1069+ gl = push_insn ( block , GuardType . new ( insn . recv . find , Types ::Fixnum , insn . state ) )
1070+ gl . type = insn . recv . find . type & Types ::Fixnum
1071+ gr = push_insn ( block , GuardType . new ( insn . args [ 0 ] . find , Types ::Fixnum , insn . state ) )
1072+ gr . type = insn . args [ 0 ] . find . type & Types ::Fixnum
10891073
10901074 # Emit specialized op
10911075 specialized = case FIXNUM_SEND_MAP [ insn . method_name ]
@@ -1098,7 +1082,7 @@ def type_specialize
10981082 end
10991083 result = push_insn ( block , specialized )
11001084 result . type = infer_type ( result )
1101- make_equal_to ( insn , result )
1085+ insn . make_equal_to ( result )
11021086 end
11031087 end
11041088 end
@@ -1117,13 +1101,13 @@ def fold_constants
11171101 old_insns = block . insns . dup
11181102 block . insns . clear
11191103 old_insns . each do |insn_id |
1120- insn = find ( insn_id )
1104+ insn = insn_id . find
11211105 replacement = case insn
11221106
11231107 # Guard elimination: if val already has the guarded type, forward
11241108 when GuardType
1125- if is_a? ( insn . val , insn . guard_type )
1126- make_equal_to ( insn , find ( insn . val ) )
1109+ if insn . val . find . type <= insn . guard_type
1110+ insn . make_equal_to ( insn . val )
11271111 next # drop from block
11281112 end
11291113 insn
@@ -1138,7 +1122,7 @@ def fold_constants
11381122
11391123 # Test folding on known truthy/falsy values
11401124 when Test
1141- val_type = type_of ( insn . val )
1125+ val_type = insn . val . find . type
11421126 if val_type <= Types ::NilClass || val_type <= Types ::FalseClass
11431127 new_insn ( Const . new ( false , Types ::FalseClass ) )
11441128 elsif val_type <= Types ::Fixnum || val_type <= Types ::TrueClass || val_type <= Types ::String
@@ -1149,9 +1133,8 @@ def fold_constants
11491133
11501134 # Branch simplification: fold IfTrue/IfFalse on known booleans
11511135 when IfTrue
1152- val_type = type_of ( insn . val )
1136+ val_type = insn . val . find . type
11531137 if val_type <= Types ::TrueClass
1154- # Always taken → replace with Jump
11551138 new_insn ( Jump . new ( insn . target ) )
11561139 elsif val_type <= Types ::FalseClass
11571140 next # never taken → drop
@@ -1160,9 +1143,8 @@ def fold_constants
11601143 end
11611144
11621145 when IfFalse
1163- val_type = type_of ( insn . val )
1146+ val_type = insn . val . find . type
11641147 if val_type <= Types ::FalseClass
1165- # Always taken → replace with Jump
11661148 new_insn ( Jump . new ( insn . target ) )
11671149 elsif val_type <= Types ::TrueClass
11681150 next # never taken → drop
@@ -1176,7 +1158,7 @@ def fold_constants
11761158
11771159 # If we created a new instruction, link old→new in union-find and infer type
11781160 if !replacement . equal? ( insn ) && replacement . type != Types ::Empty
1179- make_equal_to ( insn , replacement )
1161+ insn . make_equal_to ( replacement )
11801162 replacement . type = infer_type ( replacement )
11811163 end
11821164 push_insn_id ( block , replacement )
@@ -1196,7 +1178,7 @@ def clean_cfg
11961178 num_in_edges = ::Array . new ( @blocks . size , 0 )
11971179 rpo . each do |block |
11981180 block . insns . each do |insn |
1199- insn = find ( insn )
1181+ insn = insn . find
12001182 case insn
12011183 when Jump then num_in_edges [ insn . target . target . id ] += 1
12021184 when IfTrue then num_in_edges [ insn . target . target . id ] += 1
@@ -1233,11 +1215,11 @@ def eliminate_dead_code
12331215 next if necessary . include? ( insn . object_id )
12341216 necessary << insn . object_id
12351217 # Follow union-find to canonical insn and mark its operands
1236- canonical = find ( insn )
1218+ canonical = insn . find
12371219 necessary << canonical . object_id
12381220 canonical . operands . each do |op |
12391221 next unless op . is_a? ( Insn )
1240- worklist << find ( op )
1222+ worklist << op . find
12411223 end
12421224 end
12431225
@@ -1272,7 +1254,7 @@ def global_value_numbering
12721254 if key
12731255 existing = current_map [ key ]
12741256 if existing && !existing . equal? ( canonical )
1275- make_equal_to ( canonical , existing )
1257+ canonical . make_equal_to ( existing )
12761258 next # drop duplicate from block
12771259 else
12781260 current_map [ key ] = canonical
@@ -1308,7 +1290,7 @@ def push_insn_id(block, insn)
13081290 def absorb_dst_block ( num_in_edges , block )
13091291 last = block . insns . last
13101292 return false unless last
1311- last = find ( last )
1293+ last = last . find
13121294 return false unless last . is_a? ( Jump )
13131295
13141296 target = last . target . target
@@ -1317,7 +1299,7 @@ def absorb_dst_block(num_in_edges, block)
13171299
13181300 # Link block params → jump args via union-find
13191301 target . params . each_with_index do |param , i |
1320- make_equal_to ( param , find ( last . target . args [ i ] ) )
1302+ param . make_equal_to ( last . target . args [ i ] )
13211303 end
13221304
13231305 # Remove the Jump, append target's insns
@@ -1329,8 +1311,8 @@ def absorb_dst_block(num_in_edges, block)
13291311 end
13301312
13311313 def fold_fixnum_bop ( insn )
1332- lt = type_of ( insn . left )
1333- rt = type_of ( insn . right )
1314+ lt = insn . left . find . type
1315+ rt = insn . right . find . type
13341316 return nil unless lt . has_const? && rt . has_const? && lt . fixnum? && rt . fixnum?
13351317 result = case insn
13361318 when FixnumAdd then lt . const_val + rt . const_val
@@ -1341,8 +1323,8 @@ def fold_fixnum_bop(insn)
13411323 end
13421324
13431325 def fold_fixnum_pred ( insn )
1344- lt = type_of ( insn . left )
1345- rt = type_of ( insn . right )
1326+ lt = insn . left . find . type
1327+ rt = insn . right . find . type
13461328 return nil unless lt . has_const? && rt . has_const? && lt . fixnum? && rt . fixnum?
13471329 result = case insn
13481330 when FixnumLt then lt . const_val < rt . const_val
0 commit comments