@@ -261,15 +261,19 @@ def adjust_higher(self, eff: StackEffect) -> None:
261
261
self .final_offset .higher (eff )
262
262
263
263
def adjust (self , offset : StackOffset ) -> None :
264
- for down in offset .deep :
264
+ deep = list (offset .deep )
265
+ high = list (offset .high )
266
+ for down in deep :
265
267
self .adjust_deeper (down )
266
- for up in offset . high :
268
+ for up in high :
267
269
self .adjust_higher (up )
268
270
269
271
def adjust_inverse (self , offset : StackOffset ) -> None :
270
- for down in offset .deep :
272
+ deep = list (offset .deep )
273
+ high = list (offset .high )
274
+ for down in deep :
271
275
self .adjust_higher (down )
272
- for up in offset . high :
276
+ for up in high :
273
277
self .adjust_deeper (up )
274
278
275
279
def collect_vars (self ) -> dict [str , StackEffect ]:
@@ -426,15 +430,26 @@ def write_components(
426
430
)
427
431
428
432
if mgr .instr .name in ("_PUSH_FRAME" , "_POP_FRAME" ):
429
- # Adjust stack to min_offset (input effects materialized)
433
+ # Adjust stack to min_offset.
434
+ # This means that all input effects of this instruction
435
+ # are materialized, but not its output effects.
436
+ # That's as intended, since these two are so special.
430
437
out .stack_adjust (mgr .min_offset .deep , mgr .min_offset .high )
431
- # Use clone() since adjust_inverse() mutates final_offset
432
- mgr .adjust_inverse (mgr .final_offset .clone ())
438
+ # However, for tier 2, pretend the stack is at final offset.
439
+ mgr .adjust_inverse (mgr .final_offset )
440
+ if tier == TIER_ONE :
441
+ # TODO: Check in analyzer that _{PUSH,POP}_FRAME is last.
442
+ assert (
443
+ mgr is managers [- 1 ]
444
+ ), f"Expected { mgr .instr .name !r} to be the last uop"
445
+ assert_no_pokes (managers )
433
446
434
447
if mgr .instr .name == "SAVE_CURRENT_IP" :
435
448
next_instr_is_set = True
436
449
if cache_offset :
437
450
out .emit (f"next_instr += { cache_offset } ;" )
451
+ if tier == TIER_ONE :
452
+ assert_no_pokes (managers )
438
453
439
454
if len (parts ) == 1 :
440
455
mgr .instr .write_body (out , 0 , mgr .active_caches , tier )
@@ -443,19 +458,41 @@ def write_components(
443
458
mgr .instr .write_body (out , - 4 , mgr .active_caches , tier )
444
459
445
460
if mgr is managers [- 1 ] and not next_instr_is_set :
446
- # TODO: Explain why this adjustment is needed.
461
+ # Adjust the stack to its final depth, *then* write the
462
+ # pokes for all preceding uops.
463
+ # Note that for array output effects we may still write
464
+ # past the stack top.
447
465
out .stack_adjust (mgr .final_offset .deep , mgr .final_offset .high )
448
- # Use clone() since adjust_inverse() mutates final_offset
449
- mgr .adjust_inverse (mgr .final_offset .clone ())
466
+ write_all_pokes (mgr .final_offset , managers , out )
450
467
468
+ return next_instr_is_set
469
+
470
+
471
+ def assert_no_pokes (managers : list [EffectManager ]) -> None :
472
+ for mgr in managers :
451
473
for poke in mgr .pokes :
452
474
if not poke .effect .size and poke .effect .name not in mgr .instr .unmoved_names :
453
- out .assign (
454
- poke .as_stack_effect (),
455
- poke .effect ,
456
- )
475
+ assert (
476
+ poke .effect .name == UNUSED
477
+ ), f"Unexpected poke of { poke .effect .name } in { mgr .instr .name !r} "
457
478
458
- return next_instr_is_set
479
+
480
+ def write_all_pokes (
481
+ offset : StackOffset , managers : list [EffectManager ], out : Formatter
482
+ ) -> None :
483
+ # Emit all remaining pushes (pokes)
484
+ for m in managers :
485
+ m .adjust_inverse (offset )
486
+ write_pokes (m , out )
487
+
488
+
489
+ def write_pokes (mgr : EffectManager , out : Formatter ) -> None :
490
+ for poke in mgr .pokes :
491
+ if not poke .effect .size and poke .effect .name not in mgr .instr .unmoved_names :
492
+ out .assign (
493
+ poke .as_stack_effect (),
494
+ poke .effect ,
495
+ )
459
496
460
497
461
498
def write_single_instr_for_abstract_interp (instr : Instruction , out : Formatter ) -> None :
@@ -478,8 +515,7 @@ def _write_components_for_abstract_interp(
478
515
for mgr in managers :
479
516
if mgr is managers [- 1 ]:
480
517
out .stack_adjust (mgr .final_offset .deep , mgr .final_offset .high )
481
- # Use clone() since adjust_inverse() mutates final_offset
482
- mgr .adjust_inverse (mgr .final_offset .clone ())
518
+ mgr .adjust_inverse (mgr .final_offset )
483
519
# NULL out the output stack effects
484
520
for poke in mgr .pokes :
485
521
if not poke .effect .size and poke .effect .name not in mgr .instr .unmoved_names :
0 commit comments