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(®s.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 ®s.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 ®s.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 ®s.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(®s.global, is_reload) 566 .unwrap_or_else(|_| { 567 debug!("quick_solve failed for {}", self.solver); 568 self.iterate_solution( 569 throughs, 570 ®s.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