@@ -285,11 +285,11 @@ impl<T> MoveVecWithScratch<T> {
285285 }
286286
287287 /// Do any moves go from stack to stack?
288- pub fn stack_to_stack ( & self ) -> bool {
288+ pub fn stack_to_stack ( & self , is_stack_alloc : impl Fn ( Allocation ) -> bool ) -> bool {
289289 match self {
290290 MoveVecWithScratch :: NoScratch ( moves) | MoveVecWithScratch :: Scratch ( moves) => moves
291291 . iter ( )
292- . any ( |( src, dst, _) | src . is_stack ( ) && dst . is_stack ( ) ) ,
292+ . any ( |& ( src, dst, _) | is_stack_alloc ( src ) && is_stack_alloc ( dst ) ) ,
293293 }
294294 }
295295}
@@ -320,10 +320,11 @@ impl<T> MoveVecWithScratch<T> {
320320/// Sometimes move elision will be able to clean this up a bit. But,
321321/// for simplicity reasons, let's keep the concerns separated! So we
322322/// always do the full expansion above.
323- pub struct MoveAndScratchResolver < GetReg , GetStackSlot >
323+ pub struct MoveAndScratchResolver < GetReg , GetStackSlot , IsStackAlloc >
324324where
325325 GetReg : FnMut ( ) -> Option < Allocation > ,
326326 GetStackSlot : FnMut ( ) -> Allocation ,
327+ IsStackAlloc : Fn ( Allocation ) -> bool ,
327328{
328329 /// Scratch register for stack-to-stack move expansion.
329330 stack_stack_scratch_reg : Option < Allocation > ,
@@ -335,32 +336,41 @@ where
335336 find_free_reg : GetReg ,
336337 /// Closure that gets us a stackslot, if needed.
337338 get_stackslot : GetStackSlot ,
339+ /// Closure to determine whether an `Allocation` refers to a stack slot.
340+ is_stack_alloc : IsStackAlloc ,
338341 /// The victim PReg to evict to another stackslot at every
339342 /// stack-to-stack move if a free PReg is not otherwise
340343 /// available. Provided by caller and statically chosen. This is a
341344 /// very last-ditch option, so static choice is OK.
342345 victim : PReg ,
343346}
344347
345- impl < GetReg , GetStackSlot > MoveAndScratchResolver < GetReg , GetStackSlot >
348+ impl < GetReg , GetStackSlot , IsStackAlloc > MoveAndScratchResolver < GetReg , GetStackSlot , IsStackAlloc >
346349where
347350 GetReg : FnMut ( ) -> Option < Allocation > ,
348351 GetStackSlot : FnMut ( ) -> Allocation ,
352+ IsStackAlloc : Fn ( Allocation ) -> bool ,
349353{
350- pub fn new ( find_free_reg : GetReg , get_stackslot : GetStackSlot , victim : PReg ) -> Self {
354+ pub fn new (
355+ find_free_reg : GetReg ,
356+ get_stackslot : GetStackSlot ,
357+ is_stack_alloc : IsStackAlloc ,
358+ victim : PReg ,
359+ ) -> Self {
351360 Self {
352361 stack_stack_scratch_reg : None ,
353362 stack_stack_scratch_reg_save : None ,
354363 find_free_reg,
355364 get_stackslot,
365+ is_stack_alloc,
356366 victim,
357367 }
358368 }
359369
360370 pub fn compute < T : Debug + Copy > ( mut self , moves : MoveVecWithScratch < T > ) -> MoveVec < T > {
361371 // First, do we have a vec with no stack-to-stack moves or use
362372 // of a scratch register? Fast return if so.
363- if !moves. needs_scratch ( ) && !moves. stack_to_stack ( ) {
373+ if !moves. needs_scratch ( ) && !moves. stack_to_stack ( & self . is_stack_alloc ) {
364374 return moves. without_scratch ( ) . unwrap ( ) ;
365375 }
366376
@@ -373,7 +383,7 @@ where
373383 let moves = moves. with_scratch ( scratch) ;
374384 for & ( src, dst, data) in & moves {
375385 // Do we have a stack-to-stack move? If so, resolve.
376- if src . is_stack ( ) && dst . is_stack ( ) {
386+ if ( self . is_stack_alloc ) ( src ) && ( self . is_stack_alloc ) ( dst ) {
377387 trace ! ( "scratch resolver: stack to stack: {:?} -> {:?}" , src, dst) ;
378388 // Lazily allocate a stack-to-stack scratch.
379389 if self . stack_stack_scratch_reg . is_none ( ) {
0 commit comments