regalloc: Fuse mapping lookup and removal
54343bcb75381ee8b3ae5ab09afda198395dafb2bb58260716f4a6ea78ea8534
Last-use handling searched the active register map once to find the physical register and again to remove the same mapping. Return the physical register from `rmapRemove`, allowing one traversal to both remove the mapping and release its physical register. Assisted-by: Codex:gpt-5.6-sol
1 parent
80166a83
lib/std/lang/gen/regalloc/assign.rad
+6 -6
| 218 | 218 | set rmap.virtRegs[rmap.n] = virtReg; |
|
| 219 | 219 | set rmap.physRegs[rmap.n] = physReg; |
|
| 220 | 220 | set rmap.n += 1; |
|
| 221 | 221 | } |
|
| 222 | 222 | ||
| 223 | - | /// Remove a mapping from register map. |
|
| 224 | - | fn rmapRemove(rmap: *mut RegMap, virtReg: u32) { |
|
| 223 | + | /// Remove a mapping from the register map and return its physical register. |
|
| 224 | + | fn rmapRemove(rmap: *mut RegMap, virtReg: u32) -> ?gen::Reg { |
|
| 225 | 225 | for i in 0..rmap.n { |
|
| 226 | 226 | if rmap.virtRegs[i] == virtReg { |
|
| 227 | + | let phys = rmap.physRegs[i]; |
|
| 227 | 228 | // Swap with last and decrement. |
|
| 228 | 229 | set rmap.n -= 1; |
|
| 229 | 230 | if i < rmap.n { |
|
| 230 | 231 | set rmap.virtRegs[i] = rmap.virtRegs[rmap.n]; |
|
| 231 | 232 | set rmap.physRegs[i] = rmap.physRegs[rmap.n]; |
|
| 232 | 233 | } |
|
| 233 | - | return; |
|
| 234 | + | return phys; |
|
| 234 | 235 | } |
|
| 235 | 236 | } |
|
| 236 | - | panic "rmapRemove: register not found"; |
|
| 237 | + | return nil; |
|
| 237 | 238 | } |
|
| 238 | 239 | ||
| 239 | 240 | /// Find first free register in pool, allocate it, return it. |
|
| 240 | 241 | fn findFreeInPool(usedRegs: *mut bitset::Bitset, current: *mut RegMap, ssaReg: u32, pool: *[gen::Reg]) -> ?gen::Reg { |
|
| 241 | 242 | for i in 0..pool.len { |
| 280 | 281 | ||
| 281 | 282 | /// Callback for [`il::forEachReg`]: free last uses and allocate missing uses. |
|
| 282 | 283 | fn processInstrRegCb(reg: il::Reg, ctxPtr: *mut opaque) { |
|
| 283 | 284 | let ctx = ctxPtr as *mut InstrCtx; |
|
| 284 | 285 | if not liveness::hasLaterUse(ctx.live, ctx.func, ctx.blockIdx, ctx.instrIdx, reg) { |
|
| 285 | - | if let phys = rmapFind(ctx.current, reg.n) { |
|
| 286 | + | if let phys = rmapRemove(ctx.current, reg.n) { |
|
| 286 | 287 | bitset::clear(ctx.usedRegs, *phys as u32); |
|
| 287 | - | rmapRemove(ctx.current, reg.n); |
|
| 288 | 288 | } |
|
| 289 | 289 | } |
|
| 290 | 290 | assert reg.n < ctx.assignments.len, "processInstrRegCb: register out of bounds"; |
|
| 291 | 291 | if spill::isSpilled(ctx.spillInfo, reg) { |
|
| 292 | 292 | return; // Spilled values don't get physical registers. |