1 //! Register allocator coloring pass.
2 //!
3 //! The coloring pass assigns a physical register to every SSA value with a register affinity,
4 //! under the assumption that the register pressure has been lowered sufficiently by spilling and
5 //! splitting.
6 //!
7 //! # Preconditions
8 //!
9 //! The coloring pass doesn't work on arbitrary code. Certain preconditions must be satisfied:
10 //!
11 //! 1. All instructions must be legalized and assigned an encoding. The encoding recipe guides the
12 //!    register assignments and provides exact constraints.
13 //!
14 //! 2. Instructions with tied operands must be in a coloring-friendly state. Specifically, the
15 //!    values used by the tied operands must be killed by the instruction. This can be achieved by
16 //!    inserting a `copy` to a new value immediately before the two-address instruction.
17 //!
18 //! 3. If a value is bound to more than one operand on the same instruction, the operand
19 //!    constraints must be compatible. This can also be achieved by inserting copies so the
20 //!    incompatible operands get different values.
21 //!
22 //! 4. The register pressure must be lowered sufficiently by inserting spill code. Register
23 //!    operands are allowed to read spilled values, but each such instance must be counted as using
24 //!    a register.
25 //!
26 //! 5. The code must be in Conventional SSA form. Among other things, this means that values passed
27 //!    as arguments when branching to a block must belong to the same virtual register as the
28 //!    corresponding block argument value.
29 //!
30 //! # Iteration order
31 //!
32 //! The SSA property guarantees that whenever the live range of two values overlap, one of the
33 //! values will be live at the definition point of the other value. If we visit the instructions in
34 //! a topological order relative to the dominance relation, we can assign colors to the values
35 //! defined by the instruction and only consider the colors of other values that are live at the
36 //! instruction.
37 //!
38 //! The first time we see a branch to a block, the block's argument values are colored to match the
39 //! registers currently holding branch argument values passed to the predecessor branch. By
40 //! visiting blocks in a CFG topological order, we guarantee that at least one predecessor branch has
41 //! been visited before the destination block. Therefore, the block's arguments are already colored.
42 //!
43 //! The exception is the entry block whose arguments are colored from the ABI requirements.
44 
45 use crate::cursor::{Cursor, EncCursor};
46 use crate::dominator_tree::DominatorTree;
47 use crate::flowgraph::ControlFlowGraph;
48 use crate::ir::{ArgumentLoc, InstBuilder, ValueDef};
49 use crate::ir::{Block, Function, Inst, InstructionData, Layout, Opcode, SigRef, Value, ValueLoc};
50 use crate::isa::{regs_overlap, RegClass, RegInfo, RegUnit};
51 use crate::isa::{ConstraintKind, EncInfo, OperandConstraint, RecipeConstraints, TargetIsa};
52 use crate::packed_option::PackedOption;
53 use crate::regalloc::affinity::Affinity;
54 use crate::regalloc::diversion::RegDiversions;
55 use crate::regalloc::live_value_tracker::{LiveValue, LiveValueTracker};
56 use crate::regalloc::liveness::Liveness;
57 use crate::regalloc::liverange::LiveRange;
58 use crate::regalloc::register_set::RegisterSet;
59 use crate::regalloc::solver::{Solver, SolverError};
60 use crate::timing;
61 use core::mem;
62 use log::debug;
63 
64 /// Data structures for the coloring pass.
65 ///
66 /// These are scratch space data structures that can be reused between invocations.
67 pub struct Coloring {
68     divert: RegDiversions,
69     solver: Solver,
70 }
71 
72 /// Kinds of ABI parameters.
73 enum AbiParams {
74     Parameters(SigRef),
75     Returns,
76 }
77 
78 /// Bundle of references that the coloring algorithm needs.
79 ///
80 /// Some of the needed mutable references are passed around as explicit function arguments so we
81 /// can avoid many fights with the borrow checker over mutable borrows of `self`. This includes the
82 /// `Function` and `LiveValueTracker` references.
83 ///
84 /// Immutable context information and mutable references that don't need to be borrowed across
85 /// method calls should go in this struct.
86 struct Context<'a> {
87     // Current instruction as well as reference to function and ISA.
88     cur: EncCursor<'a>,
89 
90     // Cached ISA information.
91     // We save it here to avoid frequent virtual function calls on the `TargetIsa` trait object.
92     reginfo: RegInfo,
93     encinfo: EncInfo,
94 
95     // References to contextual data structures we need.
96     cfg: &'a ControlFlowGraph,
97     domtree: &'a DominatorTree,
98     liveness: &'a mut Liveness,
99 
100     // References to working set data structures.
101     // If we need to borrow out of a data structure across a method call, it must be passed as a
102     // function argument instead, see the `LiveValueTracker` arguments.
103     divert: &'a mut RegDiversions,
104     solver: &'a mut Solver,
105 
106     // Pristine set of registers that the allocator can use.
107     // This set remains immutable, we make clones.
108     usable_regs: RegisterSet,
109 
110     uses_pinned_reg: bool,
111 }
112 
113 impl Coloring {
114     /// Allocate scratch space data structures for the coloring pass.
new() -> Self115     pub fn new() -> Self {
116         Self {
117             divert: RegDiversions::new(),
118             solver: Solver::new(),
119         }
120     }
121 
122     /// Clear all data structures in this coloring pass.
clear(&mut self)123     pub fn clear(&mut self) {
124         self.divert.clear();
125         self.solver.clear();
126     }
127 
128     /// Run the coloring algorithm over `func`.
run( &mut self, isa: &dyn TargetIsa, func: &mut Function, cfg: &ControlFlowGraph, domtree: &DominatorTree, liveness: &mut Liveness, tracker: &mut LiveValueTracker, )129     pub fn run(
130         &mut self,
131         isa: &dyn TargetIsa,
132         func: &mut Function,
133         cfg: &ControlFlowGraph,
134         domtree: &DominatorTree,
135         liveness: &mut Liveness,
136         tracker: &mut LiveValueTracker,
137     ) {
138         let _tt = timing::ra_coloring();
139         debug!("Coloring for:\n{}", func.display(isa));
140         let mut ctx = Context {
141             usable_regs: isa.allocatable_registers(func),
142             uses_pinned_reg: isa.flags().enable_pinned_reg(),
143             cur: EncCursor::new(func, isa),
144             reginfo: isa.register_info(),
145             encinfo: isa.encoding_info(),
146             cfg,
147             domtree,
148             liveness,
149             divert: &mut self.divert,
150             solver: &mut self.solver,
151         };
152         ctx.run(tracker)
153     }
154 }
155 
156 impl<'a> Context<'a> {
157     /// Is the pinned register usage enabled, and is this register the pinned register?
158     #[inline]
is_pinned_reg(&self, rc: RegClass, reg: RegUnit) -> bool159     fn is_pinned_reg(&self, rc: RegClass, reg: RegUnit) -> bool {
160         rc.is_pinned_reg(self.uses_pinned_reg, reg)
161     }
162 
163     /// Run the coloring algorithm.
run(&mut self, tracker: &mut LiveValueTracker)164     fn run(&mut self, tracker: &mut LiveValueTracker) {
165         self.cur
166             .func
167             .locations
168             .resize(self.cur.func.dfg.num_values());
169 
170         // Visit blocks in reverse post-order. We need to ensure that at least one predecessor has
171         // been visited before each block. That guarantees that the block arguments have been colored.
172         for &block in self.domtree.cfg_postorder().iter().rev() {
173             self.visit_block(block, tracker);
174         }
175     }
176 
177     /// Visit `block`, assuming that the immediate dominator has already been visited.
visit_block(&mut self, block: Block, tracker: &mut LiveValueTracker)178     fn visit_block(&mut self, block: Block, tracker: &mut LiveValueTracker) {
179         debug!("Coloring {}:", block);
180         let mut regs = self.visit_block_header(block, tracker);
181         tracker.drop_dead_params();
182 
183         // Now go through the instructions in `block` and color the values they define.
184         self.cur.goto_top(block);
185         while let Some(inst) = self.cur.next_inst() {
186             self.cur.use_srcloc(inst);
187             let opcode = self.cur.func.dfg[inst].opcode();
188             if !opcode.is_ghost() {
189                 // This is an instruction which either has an encoding or carries ABI-related
190                 // register allocation constraints.
191                 let enc = self.cur.func.encodings[inst];
192                 let constraints = self.encinfo.operand_constraints(enc);
193                 if self.visit_inst(inst, constraints, tracker, &mut regs) {
194                     self.replace_global_defines(inst, tracker);
195                     // Restore cursor location after `replace_global_defines` moves it.
196                     // We want to revisit the copy instructions it inserted.
197                     self.cur.goto_inst(inst);
198                 }
199             } else {
200                 // This is a ghost instruction with no encoding and no extra constraints.
201                 let (_throughs, kills) = tracker.process_ghost(inst);
202                 self.process_ghost_kills(kills, &mut regs);
203             }
204             tracker.drop_dead(inst);
205 
206             // We are not able to insert any regmove for diversion or un-diversion after the first
207             // branch. Instead, we record the diversion to be restored at the entry of the next block,
208             // which should have a single predecessor.
209             if opcode.is_branch() {
210                 // The next instruction is necessarily an unconditional branch.
211                 if let Some(branch) = self.cur.next_inst() {
212                     debug!(
213                         "Skip coloring {}\n    from {}\n    with diversions {}",
214                         self.cur.display_inst(branch),
215                         regs.input.display(&self.reginfo),
216                         self.divert.display(&self.reginfo)
217                     );
218                     use crate::ir::instructions::BranchInfo::*;
219                     let target = match self.cur.func.dfg.analyze_branch(branch) {
220                         NotABranch | Table(_, _) => panic!(
221                             "unexpected instruction {} after a conditional branch",
222                             self.cur.display_inst(branch)
223                         ),
224                         SingleDest(block, _) => block,
225                     };
226 
227                     // We have a single branch with a single target, and a block with a single
228                     // predecessor. Thus we can forward the diversion set to the next block.
229                     if self.cfg.pred_iter(target).count() == 1 {
230                         // Transfer the diversion to the next block.
231                         self.divert
232                             .save_for_block(&mut self.cur.func.entry_diversions, target);
233                         debug!(
234                             "Set entry-diversion for {} to\n      {}",
235                             target,
236                             self.divert.display(&self.reginfo)
237                         );
238                     } else {
239                         debug_assert!(
240                             self.divert.is_empty(),
241                             "Divert set is non-empty after the terminator."
242                         );
243                     }
244                     assert_eq!(
245                         self.cur.next_inst(),
246                         None,
247                         "Unexpected instruction after a branch group."
248                     );
249                 } else {
250                     assert!(opcode.is_terminator());
251                 }
252             }
253         }
254     }
255 
256     /// Visit the `block` header.
257     ///
258     /// Initialize the set of live registers and color the arguments to `block`.
visit_block_header( &mut self, block: Block, tracker: &mut LiveValueTracker, ) -> AvailableRegs259     fn visit_block_header(
260         &mut self,
261         block: Block,
262         tracker: &mut LiveValueTracker,
263     ) -> AvailableRegs {
264         // Reposition the live value tracker and deal with the block arguments.
265         tracker.block_top(
266             block,
267             &self.cur.func.dfg,
268             self.liveness,
269             &self.cur.func.layout,
270             self.domtree,
271         );
272 
273         // Copy the content of the registered diversions to be reused at the
274         // entry of this basic block.
275         self.divert.at_block(&self.cur.func.entry_diversions, block);
276         debug!(
277             "Start {} with entry-diversion set to\n      {}",
278             block,
279             self.divert.display(&self.reginfo)
280         );
281 
282         if self.cur.func.layout.entry_block() == Some(block) {
283             // Parameters on the entry block have ABI constraints.
284             self.color_entry_params(tracker.live())
285         } else {
286             // The live-ins and parameters of a non-entry block have already been assigned a register.
287             // Reconstruct the allocatable set.
288             self.livein_regs(tracker.live())
289         }
290     }
291 
292     /// Initialize a set of allocatable registers from the values that are live-in to a block.
293     /// These values must already be colored when the dominating blocks were processed.
294     ///
295     /// Also process the block arguments which were colored when the first predecessor branch was
296     /// encountered.
livein_regs(&self, live: &[LiveValue]) -> AvailableRegs297     fn livein_regs(&self, live: &[LiveValue]) -> AvailableRegs {
298         // Start from the registers that are actually usable. We don't want to include any reserved
299         // registers in the set.
300         let mut regs = AvailableRegs::new(&self.usable_regs);
301 
302         for lv in live.iter().filter(|lv| !lv.is_dead) {
303             debug!(
304                 "Live-in: {}:{} in {}",
305                 lv.value,
306                 lv.affinity.display(&self.reginfo),
307                 self.divert
308                     .get(lv.value, &self.cur.func.locations)
309                     .display(&self.reginfo)
310             );
311             if let Affinity::Reg(rci) = lv.affinity {
312                 let rc = self.reginfo.rc(rci);
313                 let loc = self.cur.func.locations[lv.value];
314                 let reg = match loc {
315                     ValueLoc::Reg(reg) => reg,
316                     ValueLoc::Unassigned => panic!("Live-in {} wasn't assigned", lv.value),
317                     ValueLoc::Stack(ss) => {
318                         panic!("Live-in {} is in {}, should be register", lv.value, ss)
319                     }
320                 };
321                 if lv.is_local {
322                     regs.take(rc, reg, lv.is_local);
323                 } else {
324                     let loc = self.divert.get(lv.value, &self.cur.func.locations);
325                     let reg_divert = match loc {
326                         ValueLoc::Reg(reg) => reg,
327                         ValueLoc::Unassigned => {
328                             panic!("Diversion: Live-in {} wasn't assigned", lv.value)
329                         }
330                         ValueLoc::Stack(ss) => panic!(
331                             "Diversion: Live-in {} is in {}, should be register",
332                             lv.value, ss
333                         ),
334                     };
335                     regs.take_divert(rc, reg, reg_divert);
336                 }
337             }
338         }
339 
340         regs
341     }
342 
343     /// Color the parameters on the entry block.
344     ///
345     /// These are function parameters that should already have assigned register units in the
346     /// function signature.
347     ///
348     /// Return the set of remaining allocatable registers after filtering out the dead arguments.
color_entry_params(&mut self, args: &[LiveValue]) -> AvailableRegs349     fn color_entry_params(&mut self, args: &[LiveValue]) -> AvailableRegs {
350         let sig = &self.cur.func.signature;
351         debug_assert_eq!(sig.params.len(), args.len());
352 
353         let mut regs = AvailableRegs::new(&self.usable_regs);
354 
355         for (lv, abi) in args.iter().zip(&sig.params) {
356             match lv.affinity {
357                 Affinity::Reg(rci) => {
358                     let rc = self.reginfo.rc(rci);
359                     if let ArgumentLoc::Reg(reg) = abi.location {
360                         if !lv.is_dead {
361                             regs.take(rc, reg, lv.is_local);
362                         }
363                         self.cur.func.locations[lv.value] = ValueLoc::Reg(reg);
364                     } else {
365                         // This should have been fixed by the reload pass.
366                         panic!(
367                             "Entry arg {} has {} affinity, but ABI {}",
368                             lv.value,
369                             lv.affinity.display(&self.reginfo),
370                             abi.display(&self.reginfo)
371                         );
372                     }
373                 }
374                 // The spiller will have assigned an incoming stack slot already.
375                 Affinity::Stack => debug_assert!(abi.location.is_stack()),
376                 // This is a ghost value, unused in the function. Don't assign it to a location
377                 // either.
378                 Affinity::Unassigned => {}
379             }
380         }
381 
382         regs
383     }
384 
385     /// Program the input-side ABI constraints for `inst` into the constraint solver.
386     ///
387     /// ABI constraints are the fixed register assignments useds for calls and returns.
program_input_abi(&mut self, inst: Inst, abi_params: AbiParams)388     fn program_input_abi(&mut self, inst: Inst, abi_params: AbiParams) {
389         let abi_types = match abi_params {
390             AbiParams::Parameters(sig) => &self.cur.func.dfg.signatures[sig].params,
391             AbiParams::Returns => &self.cur.func.signature.returns,
392         };
393 
394         for (abi, &value) in abi_types
395             .iter()
396             .zip(self.cur.func.dfg.inst_variable_args(inst))
397         {
398             if let ArgumentLoc::Reg(reg) = abi.location {
399                 if let Affinity::Reg(rci) = self
400                     .liveness
401                     .get(value)
402                     .expect("ABI register must have live range")
403                     .affinity
404                 {
405                     let rc = self.reginfo.rc(rci);
406                     let cur_reg = self.divert.reg(value, &self.cur.func.locations);
407                     self.solver.reassign_in(value, rc, cur_reg, reg);
408                 } else {
409                     panic!("ABI argument {} should be in a register", value);
410                 }
411             }
412         }
413     }
414 
415     /// Color the values defined by `inst` and insert any necessary shuffle code to satisfy
416     /// instruction constraints.
417     ///
418     /// Update `regs` to reflect the allocated registers after `inst`, including removing any dead
419     /// or killed values from the set.
420     ///
421     /// Returns true when the global values defined by `inst` must be replaced by local values.
visit_inst( &mut self, inst: Inst, constraints: Option<&RecipeConstraints>, tracker: &mut LiveValueTracker, regs: &mut AvailableRegs, ) -> bool422     fn visit_inst(
423         &mut self,
424         inst: Inst,
425         constraints: Option<&RecipeConstraints>,
426         tracker: &mut LiveValueTracker,
427         regs: &mut AvailableRegs,
428     ) -> bool {
429         debug!(
430             "Coloring {}\n    from {}",
431             self.cur.display_inst(inst),
432             regs.input.display(&self.reginfo),
433         );
434 
435         // block whose arguments should be colored to match the current branch instruction's
436         // arguments.
437         let mut color_dest_args = None;
438 
439         // Program the solver with register constraints for the input side.
440         self.solver.reset(&regs.input);
441 
442         if let Some(constraints) = constraints {
443             self.program_input_constraints(inst, constraints.ins);
444         }
445 
446         let call_sig = self.cur.func.dfg.call_signature(inst);
447         if let Some(sig) = call_sig {
448             self.program_input_abi(inst, AbiParams::Parameters(sig));
449         } else if self.cur.func.dfg[inst].opcode().is_return() {
450             self.program_input_abi(inst, AbiParams::Returns);
451         } else if self.cur.func.dfg[inst].opcode().is_branch() {
452             // This is a branch, so we need to make sure that globally live values are in their
453             // global registers. For blocks that take arguments, we also need to place the argument
454             // values in the expected registers.
455             if let Some(dest) = self.cur.func.dfg[inst].branch_destination() {
456                 if self.program_block_arguments(inst, dest) {
457                     color_dest_args = Some(dest);
458                 }
459             } else {
460                 // This is a multi-way branch like `br_table`. We only support arguments on
461                 // single-destination branches.
462                 debug_assert_eq!(
463                     self.cur.func.dfg.inst_variable_args(inst).len(),
464                     0,
465                     "Can't handle block arguments: {}",
466                     self.cur.display_inst(inst)
467                 );
468                 self.undivert_regs(|lr, _| !lr.is_local());
469             }
470         }
471 
472         if self.solver.has_fixed_input_conflicts() {
473             self.divert_fixed_input_conflicts(tracker.live());
474         }
475 
476         self.solver.inputs_done();
477 
478         // Update the live value tracker with this instruction.
479         let (throughs, kills, defs) = tracker.process_inst(inst, &self.cur.func.dfg, self.liveness);
480 
481         // Get rid of the killed values.
482         for lv in kills {
483             if let Affinity::Reg(rci) = lv.affinity {
484                 let rc = self.reginfo.rc(rci);
485                 let reg = self.divert.reg(lv.value, &self.cur.func.locations);
486 
487                 if self.is_pinned_reg(rc, reg) {
488                     // Don't kill the pinned reg, either in the local or global register sets.
489                     debug_assert!(lv.is_local, "pinned register SSA value can't be global");
490                     continue;
491                 }
492 
493                 debug!(
494                     "    kill {} in {} ({} {})",
495                     lv.value,
496                     self.reginfo.display_regunit(reg),
497                     if lv.is_local { "local" } else { "global" },
498                     rc
499                 );
500                 self.solver.add_kill(lv.value, rc, reg);
501 
502                 // Update the global register set which has no diversions.
503                 if !lv.is_local {
504                     regs.global
505                         .free(rc, self.cur.func.locations[lv.value].unwrap_reg());
506                 }
507             }
508         }
509 
510         // This aligns with the "    from" line at the top of the function.
511         debug!("    glob {}", regs.global.display(&self.reginfo));
512 
513         // This flag is set when the solver failed to find a solution for the global defines that
514         // doesn't interfere with `regs.global`. We need to rewrite all of `inst`s global defines
515         // as local defines followed by copies.
516         let mut replace_global_defines = false;
517 
518         // Program the fixed output constraints before the general defines. This allows us to
519         // detect conflicts between fixed outputs and tied operands where the input value hasn't
520         // been converted to a solver variable.
521         if let Some(constraints) = constraints {
522             if constraints.fixed_outs {
523                 self.program_fixed_outputs(
524                     constraints.outs,
525                     defs,
526                     throughs,
527                     &mut replace_global_defines,
528                     &regs.global,
529                 );
530             }
531         }
532 
533         if let Some(sig) = call_sig {
534             self.program_output_abi(
535                 sig,
536                 defs,
537                 throughs,
538                 &mut replace_global_defines,
539                 &regs.global,
540             );
541         }
542 
543         if let Some(constraints) = constraints {
544             self.program_output_constraints(
545                 inst,
546                 constraints.outs,
547                 defs,
548                 &mut replace_global_defines,
549                 &regs.global,
550             );
551         }
552 
553         // Finally, we've fully programmed the constraint solver.
554         // We expect a quick solution in most cases.
555         let is_reload = match &self.cur.func.dfg[inst] {
556             InstructionData::Unary {
557                 opcode: Opcode::Fill,
558                 ..
559             } => true,
560             _ => false,
561         };
562 
563         let output_regs = self
564             .solver
565             .quick_solve(&regs.global, is_reload)
566             .unwrap_or_else(|_| {
567                 debug!("quick_solve failed for {}", self.solver);
568                 self.iterate_solution(
569                     throughs,
570                     &regs.global,
571                     &mut replace_global_defines,
572                     is_reload,
573                 )
574             });
575 
576         // The solution and/or fixed input constraints may require us to shuffle the set of live
577         // registers around.
578         self.shuffle_inputs(&mut regs.input);
579 
580         // If this is the first time we branch to `dest`, color its arguments to match the current
581         // register state.
582         if let Some(dest) = color_dest_args {
583             self.color_block_params(inst, dest);
584         }
585 
586         // Apply the solution to the defs.
587         for v in self.solver.vars().iter().filter(|&v| v.is_define()) {
588             self.cur.func.locations[v.value] = ValueLoc::Reg(v.solution);
589         }
590 
591         // Tied defs are not part of the solution above.
592         // Copy register assignments from tied inputs to tied outputs.
593         if let Some(constraints) = constraints {
594             if constraints.tied_ops {
595                 for (constraint, lv) in constraints.outs.iter().zip(defs) {
596                     if let ConstraintKind::Tied(num) = constraint.kind {
597                         let arg = self.cur.func.dfg.inst_args(inst)[num as usize];
598                         let reg = self.divert.reg(arg, &self.cur.func.locations);
599                         self.cur.func.locations[lv.value] = ValueLoc::Reg(reg);
600                     }
601                 }
602             }
603         }
604 
605         // Update `regs` for the next instruction.
606         regs.input = output_regs;
607         for lv in defs {
608             let loc = self.cur.func.locations[lv.value];
609             debug!(
610                 "    color {} -> {}{}",
611                 lv.value,
612                 loc.display(&self.reginfo),
613                 if lv.is_local {
614                     ""
615                 } else if replace_global_defines {
616                     " (global to be replaced)"
617                 } else {
618                     " (global)"
619                 }
620             );
621 
622             if let Affinity::Reg(rci) = lv.affinity {
623                 let rc = self.reginfo.rc(rci);
624                 let reg = loc.unwrap_reg();
625 
626                 debug_assert!(
627                     !self.is_pinned_reg(rc, reg)
628                         || self.cur.func.dfg[inst].opcode() == Opcode::GetPinnedReg,
629                     "pinned register may not be part of outputs for '{}'.",
630                     self.cur.func.dfg[inst].opcode()
631                 );
632 
633                 if self.is_pinned_reg(rc, reg) {
634                     continue;
635                 }
636 
637                 // Remove the dead defs.
638                 if lv.endpoint == inst {
639                     regs.input.free(rc, reg);
640                     debug_assert!(lv.is_local);
641                 }
642 
643                 // Track globals in their undiverted locations.
644                 if !lv.is_local && !replace_global_defines {
645                     regs.global.take(rc, reg);
646                 }
647             }
648         }
649 
650         self.forget_diverted(kills);
651 
652         replace_global_defines
653     }
654 
655     /// Program the input-side constraints for `inst` into the constraint solver.
program_input_constraints(&mut self, inst: Inst, constraints: &[OperandConstraint])656     fn program_input_constraints(&mut self, inst: Inst, constraints: &[OperandConstraint]) {
657         for (constraint, &arg_val) in constraints
658             .iter()
659             .zip(self.cur.func.dfg.inst_args(inst))
660             .filter(|&(constraint, _)| constraint.kind != ConstraintKind::Stack)
661         {
662             // Reload pass is supposed to ensure that all arguments to register operands are
663             // already in a register.
664             let cur_reg = self.divert.reg(arg_val, &self.cur.func.locations);
665             match constraint.kind {
666                 ConstraintKind::FixedReg(regunit) => {
667                     // Add the fixed constraint even if `cur_reg == regunit`.
668                     // It is possible that we will want to convert the value to a variable later,
669                     // and this identity assignment prevents that from happening.
670                     self.solver
671                         .reassign_in(arg_val, constraint.regclass, cur_reg, regunit);
672                 }
673                 ConstraintKind::FixedTied(regunit) => {
674                     // The pinned register may not be part of a fixed tied requirement. If this
675                     // becomes the case, then it must be changed to a different register.
676                     debug_assert!(
677                         !self.is_pinned_reg(constraint.regclass, regunit),
678                         "see comment above"
679                     );
680                     // See comment right above.
681                     self.solver
682                         .reassign_in(arg_val, constraint.regclass, cur_reg, regunit);
683                 }
684                 ConstraintKind::Tied(_) => {
685                     if self.is_pinned_reg(constraint.regclass, cur_reg) {
686                         // Divert the pinned register; it shouldn't be reused for a tied input.
687                         if self.solver.can_add_var(constraint.regclass, cur_reg) {
688                             self.solver.add_var(arg_val, constraint.regclass, cur_reg);
689                         }
690                     } else if !constraint.regclass.contains(cur_reg) {
691                         self.solver.add_var(arg_val, constraint.regclass, cur_reg);
692                     }
693                 }
694                 ConstraintKind::Reg => {
695                     if !constraint.regclass.contains(cur_reg) {
696                         self.solver.add_var(arg_val, constraint.regclass, cur_reg);
697                     }
698                 }
699                 ConstraintKind::Stack => unreachable!(),
700             }
701         }
702     }
703 
704     /// Program the complete set of input constraints into the solver.
705     ///
706     /// The `program_input_constraints()` function above will not tell the solver about any values
707     /// that are already assigned to appropriate registers. This is normally fine, but if we want
708     /// to add additional variables to help the solver, we need to make sure that they are
709     /// constrained properly.
710     ///
711     /// This function completes the work of `program_input_constraints()` by calling `add_var` for
712     /// all values used by the instruction.
program_complete_input_constraints(&mut self)713     fn program_complete_input_constraints(&mut self) {
714         let inst = self.cur.current_inst().expect("Not on an instruction");
715         let constraints = self
716             .encinfo
717             .operand_constraints(self.cur.func.encodings[inst])
718             .expect("Current instruction not encoded")
719             .ins;
720 
721         for (constraint, &arg_val) in constraints.iter().zip(self.cur.func.dfg.inst_args(inst)) {
722             match constraint.kind {
723                 ConstraintKind::Reg | ConstraintKind::Tied(_) => {
724                     let cur_reg = self.divert.reg(arg_val, &self.cur.func.locations);
725 
726                     // This is the opposite condition of `program_input_constraints()`. The pinned
727                     // register mustn't be added back as a variable.
728                     if constraint.regclass.contains(cur_reg)
729                         && !self.is_pinned_reg(constraint.regclass, cur_reg)
730                     {
731                         // This code runs after calling `solver.inputs_done()` so we must identify
732                         // the new variable as killed or live-through.
733                         let layout = &self.cur.func.layout;
734                         if self.liveness[arg_val].killed_at(inst, layout.pp_block(inst), layout) {
735                             self.solver
736                                 .add_killed_var(arg_val, constraint.regclass, cur_reg);
737                         } else {
738                             self.solver
739                                 .add_through_var(arg_val, constraint.regclass, cur_reg);
740                         }
741                     }
742                 }
743                 ConstraintKind::FixedReg(_)
744                 | ConstraintKind::FixedTied(_)
745                 | ConstraintKind::Stack => {}
746             }
747         }
748     }
749 
750     /// Prepare for a branch to `dest`.
751     ///
752     /// 1. Any values that are live-in to `dest` must be un-diverted so they live in their globally
753     ///    assigned register.
754     /// 2. If the `dest` block takes arguments, reassign the branch argument values to the matching
755     ///    registers.
756     ///
757     /// Returns true if this is the first time a branch to `dest` is seen, so the `dest` argument
758     /// values should be colored after `shuffle_inputs`.
program_block_arguments(&mut self, inst: Inst, dest: Block) -> bool759     fn program_block_arguments(&mut self, inst: Inst, dest: Block) -> bool {
760         // Find diverted registers that are live-in to `dest` and reassign them to their global
761         // home.
762         //
763         // Values with a global live range that are not live in to `dest` could appear as branch
764         // arguments, so they can't always be un-diverted.
765         self.undivert_regs(|lr, layout| lr.is_livein(dest, layout));
766 
767         // Now handle the block arguments.
768         let br_args = self.cur.func.dfg.inst_variable_args(inst);
769         let dest_args = self.cur.func.dfg.block_params(dest);
770         debug_assert_eq!(br_args.len(), dest_args.len());
771         for (&dest_arg, &br_arg) in dest_args.iter().zip(br_args) {
772             // The first time we encounter a branch to `dest`, we get to pick the location. The
773             // following times we see a branch to `dest`, we must follow suit.
774             match self.cur.func.locations[dest_arg] {
775                 ValueLoc::Unassigned => {
776                     // This is the first branch to `dest`, so we should color `dest_arg` instead of
777                     // `br_arg`. However, we don't know where `br_arg` will end up until
778                     // after `shuffle_inputs`. See `color_block_params` below.
779                     //
780                     // It is possible for `dest_arg` to have no affinity, and then it should simply
781                     // be ignored.
782                     if self.liveness[dest_arg].affinity.is_reg() {
783                         return true;
784                     }
785                 }
786                 ValueLoc::Reg(dest_reg) => {
787                     // We've branched to `dest` before. Make sure we use the correct argument
788                     // registers by reassigning `br_arg`.
789                     if let Affinity::Reg(rci) = self.liveness[br_arg].affinity {
790                         let rc = self.reginfo.rc(rci);
791                         let br_reg = self.divert.reg(br_arg, &self.cur.func.locations);
792                         self.solver.reassign_in(br_arg, rc, br_reg, dest_reg);
793                     } else {
794                         panic!("Branch argument {} is not in a register", br_arg);
795                     }
796                 }
797                 ValueLoc::Stack(ss) => {
798                     // The spiller should already have given us identical stack slots.
799                     debug_assert_eq!(ValueLoc::Stack(ss), self.cur.func.locations[br_arg]);
800                 }
801             }
802         }
803 
804         // No `dest` arguments need coloring.
805         false
806     }
807 
808     /// Knowing that we've never seen a branch to `dest` before, color its parameters to match our
809     /// register state.
810     ///
811     /// This function is only called when `program_block_arguments()` returned `true`.
color_block_params(&mut self, inst: Inst, dest: Block)812     fn color_block_params(&mut self, inst: Inst, dest: Block) {
813         let br_args = self.cur.func.dfg.inst_variable_args(inst);
814         let dest_args = self.cur.func.dfg.block_params(dest);
815         debug_assert_eq!(br_args.len(), dest_args.len());
816         for (&dest_arg, &br_arg) in dest_args.iter().zip(br_args) {
817             match self.cur.func.locations[dest_arg] {
818                 ValueLoc::Unassigned => {
819                     if self.liveness[dest_arg].affinity.is_reg() {
820                         let br_reg = self.divert.reg(br_arg, &self.cur.func.locations);
821                         self.cur.func.locations[dest_arg] = ValueLoc::Reg(br_reg);
822                     }
823                 }
824                 ValueLoc::Reg(_) => panic!("{} arg {} already colored", dest, dest_arg),
825                 // Spilled value consistency is verified by `program_block_arguments()` above.
826                 ValueLoc::Stack(_) => {}
827             }
828         }
829     }
830 
831     /// Find all diverted registers where `pred` returns `true` and undo their diversion so they
832     /// are reallocated to their global register assignments.
undivert_regs<Pred>(&mut self, mut pred: Pred) where Pred: FnMut(&LiveRange, &Layout) -> bool,833     fn undivert_regs<Pred>(&mut self, mut pred: Pred)
834     where
835         Pred: FnMut(&LiveRange, &Layout) -> bool,
836     {
837         for (&value, rdiv) in self.divert.iter() {
838             let lr = self
839                 .liveness
840                 .get(value)
841                 .expect("Missing live range for diverted register");
842             if pred(lr, &self.cur.func.layout) {
843                 if let Affinity::Reg(rci) = lr.affinity {
844                     let rc = self.reginfo.rc(rci);
845                     // Stack diversions should not be possible here. They only live transiently
846                     // during `shuffle_inputs()`.
847                     self.solver.reassign_in(
848                         value,
849                         rc,
850                         rdiv.to.unwrap_reg(),
851                         rdiv.from.unwrap_reg(),
852                     );
853                 } else {
854                     panic!(
855                         "Diverted register {} with {} affinity",
856                         value,
857                         lr.affinity.display(&self.reginfo)
858                     );
859                 }
860             }
861         }
862     }
863 
864     /// Find existing live values that conflict with the fixed input register constraints programmed
865     /// into the constraint solver. Convert them to solver variables so they can be diverted.
divert_fixed_input_conflicts(&mut self, live: &[LiveValue])866     fn divert_fixed_input_conflicts(&mut self, live: &[LiveValue]) {
867         for lv in live {
868             if let Affinity::Reg(rci) = lv.affinity {
869                 let toprc = self.reginfo.toprc(rci);
870                 let reg = self.divert.reg(lv.value, &self.cur.func.locations);
871                 if self.solver.is_fixed_input_conflict(toprc, reg) {
872                     debug!(
873                         "adding var to divert fixed input conflict for {}",
874                         toprc.info.display_regunit(reg)
875                     );
876                     self.solver.add_var(lv.value, toprc, reg);
877                 }
878             }
879         }
880     }
881 
882     /// Program any fixed-register output constraints into the solver. This may also detect
883     /// conflicts between live-through registers and fixed output registers. These live-through
884     /// values need to be turned into solver variables so they can be reassigned.
program_fixed_outputs( &mut self, constraints: &[OperandConstraint], defs: &[LiveValue], throughs: &[LiveValue], replace_global_defines: &mut bool, global_regs: &RegisterSet, )885     fn program_fixed_outputs(
886         &mut self,
887         constraints: &[OperandConstraint],
888         defs: &[LiveValue],
889         throughs: &[LiveValue],
890         replace_global_defines: &mut bool,
891         global_regs: &RegisterSet,
892     ) {
893         for (constraint, lv) in constraints.iter().zip(defs) {
894             match constraint.kind {
895                 ConstraintKind::FixedReg(reg) | ConstraintKind::FixedTied(reg) => {
896                     self.add_fixed_output(lv.value, constraint.regclass, reg, throughs);
897                     if !lv.is_local && !global_regs.is_avail(constraint.regclass, reg) {
898                         debug!(
899                             "Fixed output {} in {}:{} is not available in global regs",
900                             lv.value,
901                             constraint.regclass,
902                             self.reginfo.display_regunit(reg)
903                         );
904                         *replace_global_defines = true;
905                     }
906                 }
907                 ConstraintKind::Reg | ConstraintKind::Tied(_) | ConstraintKind::Stack => {}
908             }
909         }
910     }
911 
912     /// Program the output-side ABI constraints for `inst` into the constraint solver.
913     ///
914     /// That means return values for a call instruction.
program_output_abi( &mut self, sig: SigRef, defs: &[LiveValue], throughs: &[LiveValue], replace_global_defines: &mut bool, global_regs: &RegisterSet, )915     fn program_output_abi(
916         &mut self,
917         sig: SigRef,
918         defs: &[LiveValue],
919         throughs: &[LiveValue],
920         replace_global_defines: &mut bool,
921         global_regs: &RegisterSet,
922     ) {
923         // It's technically possible for a call instruction to have fixed results before the
924         // variable list of results, but we have no known instances of that.
925         // Just assume all results are variable return values.
926         debug_assert_eq!(defs.len(), self.cur.func.dfg.signatures[sig].returns.len());
927         for (i, lv) in defs.iter().enumerate() {
928             let abi = self.cur.func.dfg.signatures[sig].returns[i];
929             if let ArgumentLoc::Reg(reg) = abi.location {
930                 if let Affinity::Reg(rci) = lv.affinity {
931                     let rc = self.reginfo.rc(rci);
932                     self.add_fixed_output(lv.value, rc, reg, throughs);
933                     if !lv.is_local && !global_regs.is_avail(rc, reg) {
934                         debug!(
935                             "ABI output {} in {}:{} is not available in global regs",
936                             lv.value,
937                             rc,
938                             self.reginfo.display_regunit(reg)
939                         );
940                         *replace_global_defines = true;
941                     }
942                 } else {
943                     panic!("ABI argument {} should be in a register", lv.value);
944                 }
945             }
946         }
947     }
948 
949     /// Add a single fixed output value to the solver.
add_fixed_output( &mut self, value: Value, rc: RegClass, reg: RegUnit, throughs: &[LiveValue], )950     fn add_fixed_output(
951         &mut self,
952         value: Value,
953         rc: RegClass,
954         reg: RegUnit,
955         throughs: &[LiveValue],
956     ) {
957         // Pinned register is already unavailable in the solver, since it is copied in the
958         // available registers on entry.
959         if !self.is_pinned_reg(rc, reg) && !self.solver.add_fixed_output(rc, reg) {
960             // The fixed output conflicts with some of the live-through registers.
961             for lv in throughs {
962                 if let Affinity::Reg(rci) = lv.affinity {
963                     let toprc2 = self.reginfo.toprc(rci);
964                     let reg2 = self.divert.reg(lv.value, &self.cur.func.locations);
965                     if regs_overlap(rc, reg, toprc2, reg2) {
966                         // This live-through value is interfering with the fixed output assignment.
967                         // Convert it to a solver variable.
968                         self.solver.add_through_var(lv.value, toprc2, reg2);
969                     }
970                 }
971             }
972 
973             let ok = self.solver.add_fixed_output(rc, reg);
974             debug_assert!(ok, "Couldn't clear fixed output interference for {}", value);
975         }
976         self.cur.func.locations[value] = ValueLoc::Reg(reg);
977     }
978 
979     /// Program the output-side constraints for `inst` into the constraint solver.
980     ///
981     /// It is assumed that all fixed outputs have already been handled.
program_output_constraints( &mut self, inst: Inst, constraints: &[OperandConstraint], defs: &[LiveValue], replace_global_defines: &mut bool, global_regs: &RegisterSet, )982     fn program_output_constraints(
983         &mut self,
984         inst: Inst,
985         constraints: &[OperandConstraint],
986         defs: &[LiveValue],
987         replace_global_defines: &mut bool,
988         global_regs: &RegisterSet,
989     ) {
990         for (constraint, lv) in constraints.iter().zip(defs) {
991             match constraint.kind {
992                 ConstraintKind::FixedReg(_)
993                 | ConstraintKind::FixedTied(_)
994                 | ConstraintKind::Stack => continue,
995                 ConstraintKind::Reg => {
996                     self.solver
997                         .add_def(lv.value, constraint.regclass, !lv.is_local);
998                 }
999                 ConstraintKind::Tied(num) => {
1000                     // Find the input operand we're tied to.
1001                     // The solver doesn't care about the output value.
1002                     let arg = self.cur.func.dfg.inst_args(inst)[num as usize];
1003                     let reg = self.divert.reg(arg, &self.cur.func.locations);
1004 
1005                     if let Some(reg) =
1006                         self.solver
1007                             .add_tied_input(arg, constraint.regclass, reg, !lv.is_local)
1008                     {
1009                         // The value we're tied to has been assigned to a fixed register.
1010                         // We need to make sure that fixed output register is compatible with the
1011                         // global register set.
1012                         if !lv.is_local && !global_regs.is_avail(constraint.regclass, reg) {
1013                             debug!(
1014                                 "Tied output {} in {}:{} is not available in global regs",
1015                                 lv.value,
1016                                 constraint.regclass,
1017                                 self.reginfo.display_regunit(reg)
1018                             );
1019                             *replace_global_defines = true;
1020                         }
1021                     }
1022                 }
1023             }
1024         }
1025     }
1026 
1027     /// Try harder to find a solution to the constraint problem since `quick_solve()` failed.
1028     ///
1029     /// We may need to move more registers around before a solution is possible. Use an iterative
1030     /// algorithm that adds one more variable until a solution can be found.
iterate_solution( &mut self, throughs: &[LiveValue], global_regs: &RegisterSet, replace_global_defines: &mut bool, is_reload: bool, ) -> RegisterSet1031     fn iterate_solution(
1032         &mut self,
1033         throughs: &[LiveValue],
1034         global_regs: &RegisterSet,
1035         replace_global_defines: &mut bool,
1036         is_reload: bool,
1037     ) -> RegisterSet {
1038         // Make sure `try_add_var()` below doesn't create a variable with too loose constraints.
1039         self.program_complete_input_constraints();
1040 
1041         loop {
1042             match self.solver.real_solve(global_regs, is_reload) {
1043                 Ok(regs) => return regs,
1044                 Err(SolverError::Divert(rc)) => {
1045                     // Do we have any live-through `rc` registers that are not already variables?
1046                     let added = self.try_add_var(rc, throughs);
1047                     debug_assert!(added, "Ran out of registers in {}", rc);
1048                 }
1049                 Err(SolverError::Global(_value)) => {
1050                     debug!(
1051                         "Not enough global registers for {}, trying as local",
1052                         _value
1053                     );
1054                     // We'll clear the `is_global` flag on all solver variables and instead make a
1055                     // note to replace all global defines with local defines followed by a copy.
1056                     *replace_global_defines = true;
1057                     self.solver.clear_all_global_flags();
1058                 }
1059             };
1060         }
1061     }
1062 
1063     /// Try to add an `rc` variable to the solver from the `throughs` set.
try_add_var(&mut self, rc: RegClass, throughs: &[LiveValue]) -> bool1064     fn try_add_var(&mut self, rc: RegClass, throughs: &[LiveValue]) -> bool {
1065         debug!("Trying to add a {} reg from {} values", rc, throughs.len());
1066 
1067         for lv in throughs {
1068             if let Affinity::Reg(rci) = lv.affinity {
1069                 // The new variable gets to roam the whole top-level register class because it is
1070                 // not actually constrained by the instruction. We just want it out of the way.
1071                 let toprc2 = self.reginfo.toprc(rci);
1072                 let reg2 = self.divert.reg(lv.value, &self.cur.func.locations);
1073                 if rc.contains(reg2)
1074                     && self.solver.can_add_var(toprc2, reg2)
1075                     && !self.is_live_on_outgoing_edge(lv.value)
1076                 {
1077                     self.solver.add_through_var(lv.value, toprc2, reg2);
1078                     return true;
1079                 }
1080             }
1081         }
1082 
1083         false
1084     }
1085 
1086     /// Determine if `value` is live on a CFG edge from the current instruction.
1087     ///
1088     /// This means that the current instruction is a branch and `value` is live in to one of the
1089     /// branch destinations. Branch arguments and block parameters are not considered live on the
1090     /// edge.
is_live_on_outgoing_edge(&self, value: Value) -> bool1091     fn is_live_on_outgoing_edge(&self, value: Value) -> bool {
1092         use crate::ir::instructions::BranchInfo::*;
1093 
1094         let inst = self.cur.current_inst().expect("Not on an instruction");
1095         let layout = &self.cur.func.layout;
1096         match self.cur.func.dfg.analyze_branch(inst) {
1097             NotABranch => false,
1098             SingleDest(block, _) => {
1099                 let lr = &self.liveness[value];
1100                 lr.is_livein(block, layout)
1101             }
1102             Table(jt, block) => {
1103                 let lr = &self.liveness[value];
1104                 !lr.is_local()
1105                     && (block.map_or(false, |block| lr.is_livein(block, layout))
1106                         || self.cur.func.jump_tables[jt]
1107                             .iter()
1108                             .any(|block| lr.is_livein(*block, layout)))
1109             }
1110         }
1111     }
1112 
1113     /// Emit `regmove` instructions as needed to move the live registers into place before the
1114     /// instruction. Also update `self.divert` accordingly.
1115     ///
1116     /// The `self.cur` cursor is expected to point at the instruction. The register moves are
1117     /// inserted before.
1118     ///
1119     /// The solver needs to be reminded of the available registers before any moves are inserted.
shuffle_inputs(&mut self, regs: &mut RegisterSet)1120     fn shuffle_inputs(&mut self, regs: &mut RegisterSet) {
1121         use crate::regalloc::solver::Move::*;
1122 
1123         let spills = self.solver.schedule_moves(regs);
1124 
1125         // The move operations returned by `schedule_moves` refer to emergency spill slots by
1126         // consecutive indexes starting from 0. Map these to real stack slots.
1127         // It is very unlikely (impossible?) that we would need more than one spill per top-level
1128         // register class, so avoid allocation by using a fixed array here.
1129         let mut slot = [PackedOption::default(); 8];
1130         debug_assert!(spills <= slot.len(), "Too many spills ({})", spills);
1131 
1132         for m in self.solver.moves() {
1133             match *m {
1134                 Reg {
1135                     value,
1136                     from,
1137                     to,
1138                     rc,
1139                 } => {
1140                     debug_assert!(
1141                         !self.is_pinned_reg(rc, to),
1142                         "pinned register used in a regmove"
1143                     );
1144                     self.divert.regmove(value, from, to);
1145                     self.cur.ins().regmove(value, from, to);
1146                 }
1147                 Spill {
1148                     value,
1149                     from,
1150                     to_slot,
1151                     ..
1152                 } => {
1153                     debug_assert_eq!(slot[to_slot].expand(), None, "Overwriting slot in use");
1154                     let ss = self
1155                         .cur
1156                         .func
1157                         .stack_slots
1158                         .get_emergency_slot(self.cur.func.dfg.value_type(value), &slot[0..spills]);
1159                     slot[to_slot] = ss.into();
1160                     self.divert.regspill(value, from, ss);
1161                     self.cur.ins().regspill(value, from, ss);
1162                 }
1163                 Fill {
1164                     value,
1165                     from_slot,
1166                     to,
1167                     rc,
1168                 } => {
1169                     debug_assert!(
1170                         !self.is_pinned_reg(rc, to),
1171                         "pinned register used in a regfill"
1172                     );
1173                     // These slots are single use, so mark `ss` as available again.
1174                     let ss = slot[from_slot].take().expect("Using unallocated slot");
1175                     self.divert.regfill(value, ss, to);
1176                     self.cur.ins().regfill(value, ss, to);
1177                 }
1178             }
1179         }
1180     }
1181 
1182     /// Forget about any register diversions in `kills`.
forget_diverted(&mut self, kills: &[LiveValue])1183     fn forget_diverted(&mut self, kills: &[LiveValue]) {
1184         if self.divert.is_empty() {
1185             return;
1186         }
1187 
1188         for lv in kills {
1189             if lv.affinity.is_reg() {
1190                 self.divert.remove(lv.value);
1191             }
1192         }
1193     }
1194 
1195     /// Replace all global values defined by `inst` with local values that are then copied into the
1196     /// global value:
1197     ///
1198     ///   v1 = foo
1199     ///
1200     /// becomes:
1201     ///
1202     ///   v20 = foo
1203     ///   v1 = copy v20
1204     ///
1205     /// This is sometimes necessary when there are no global registers available that can satisfy
1206     /// the constraints on the instruction operands.
1207     ///
replace_global_defines(&mut self, inst: Inst, tracker: &mut LiveValueTracker)1208     fn replace_global_defines(&mut self, inst: Inst, tracker: &mut LiveValueTracker) {
1209         debug!("Replacing global defs on {}", self.cur.display_inst(inst));
1210 
1211         // We'll insert copies *after `inst`. Our caller will move the cursor back.
1212         self.cur.next_inst();
1213 
1214         // The tracker keeps the defs from `inst` at the end. Any dead defs have already been
1215         // removed, so it's not obvious how many defs to process
1216         for lv in tracker.live_mut().iter_mut().rev() {
1217             // Keep going until we reach a value that is not defined by `inst`.
1218             if match self.cur.func.dfg.value_def(lv.value) {
1219                 ValueDef::Result(i, _) => i != inst,
1220                 _ => true,
1221             } {
1222                 break;
1223             }
1224             if lv.is_local || !lv.affinity.is_reg() {
1225                 continue;
1226             }
1227 
1228             // Now `lv.value` is globally live and defined by `inst`. Replace it with a local live
1229             // range that is copied after `inst`.
1230             let ty = self.cur.func.dfg.value_type(lv.value);
1231             let local = self.cur.func.dfg.replace_result(lv.value, ty);
1232             self.cur.ins().with_result(lv.value).copy(local);
1233             let copy = self.cur.built_inst();
1234 
1235             // Create a live range for `local: inst -> copy`.
1236             self.liveness.create_dead(local, inst, lv.affinity);
1237             self.liveness.extend_locally(
1238                 local,
1239                 self.cur.func.layout.pp_block(inst),
1240                 copy,
1241                 &self.cur.func.layout,
1242             );
1243 
1244             // Move the definition of the global `lv.value`.
1245             self.liveness.move_def_locally(lv.value, copy);
1246 
1247             // Transfer the register coloring to `local`.
1248             let loc = mem::replace(&mut self.cur.func.locations[lv.value], ValueLoc::default());
1249             self.cur.func.locations[local] = loc;
1250 
1251             // Update `lv` to reflect the new `local` live range.
1252             lv.value = local;
1253             lv.endpoint = copy;
1254             lv.is_local = true;
1255 
1256             debug!(
1257                 "  + {} with {} in {}",
1258                 self.cur.display_inst(copy),
1259                 local,
1260                 loc.display(&self.reginfo)
1261             );
1262         }
1263         debug!("Done: {}", self.cur.display_inst(inst));
1264     }
1265 
1266     /// Process kills on a ghost instruction.
1267     /// - Forget diversions.
1268     /// - Free killed registers.
process_ghost_kills(&mut self, kills: &[LiveValue], regs: &mut AvailableRegs)1269     fn process_ghost_kills(&mut self, kills: &[LiveValue], regs: &mut AvailableRegs) {
1270         for lv in kills {
1271             if let Affinity::Reg(rci) = lv.affinity {
1272                 let rc = self.reginfo.rc(rci);
1273                 let loc = match self.divert.remove(lv.value) {
1274                     Some(loc) => loc,
1275                     None => self.cur.func.locations[lv.value],
1276                 };
1277                 regs.input.free(rc, loc.unwrap_reg());
1278                 if !lv.is_local {
1279                     regs.global
1280                         .free(rc, self.cur.func.locations[lv.value].unwrap_reg());
1281                 }
1282             }
1283         }
1284     }
1285 }
1286 
1287 /// Keep track of the set of available registers in two interference domains: all registers
1288 /// considering diversions and global registers not considering diversions.
1289 struct AvailableRegs {
1290     /// The exact set of registers available on the input side of the current instruction. This
1291     /// takes into account register diversions, and it includes both local and global live ranges.
1292     input: RegisterSet,
1293 
1294     /// Registers available for allocating globally live values. This set ignores any local values,
1295     /// and it does not account for register diversions.
1296     ///
1297     /// Global values must be allocated out of this set because conflicts with other global values
1298     /// can't be resolved with local diversions.
1299     global: RegisterSet,
1300 }
1301 
1302 impl AvailableRegs {
1303     /// Initialize both the input and global sets from `regs`.
new(regs: &RegisterSet) -> Self1304     pub fn new(regs: &RegisterSet) -> Self {
1305         Self {
1306             input: regs.clone(),
1307             global: regs.clone(),
1308         }
1309     }
1310 
1311     /// Take an un-diverted register from one or both sets.
take(&mut self, rc: RegClass, reg: RegUnit, is_local: bool)1312     pub fn take(&mut self, rc: RegClass, reg: RegUnit, is_local: bool) {
1313         self.input.take(rc, reg);
1314         if !is_local {
1315             self.global.take(rc, reg);
1316         }
1317     }
1318 
1319     /// Take a diverted register from both sets for a non-local allocation.
take_divert(&mut self, rc: RegClass, reg: RegUnit, reg_divert: RegUnit)1320     pub fn take_divert(&mut self, rc: RegClass, reg: RegUnit, reg_divert: RegUnit) {
1321         self.input.take(rc, reg_divert);
1322         self.global.take(rc, reg);
1323     }
1324 }
1325